ARTS-week-2

用户头像
youngitachi
关注
发布于: 2020 年 06 月 07 日

1. Algorithm

题目1 反转链表2

https://leetcode.com/problems/reverse-linked-list-ii/

找了个反转链表的题目来做。面试的算法题一般都很爱考链表,这次练习也算是有的放矢。

问题描述:

给一个链表,反转其中第m到n个节点。其中1 <= m <= n <= 链表长度。序号从1开始。还有个要求,只能遍历链表一次

如果m = 1,n = 链表长度,那就是普通的反转链表了。因此这个题目是反转链表的推广。其实这个题目唯一的难点在于边界,即第m和n个节点及其相邻位置的处理。例如m-1的next应该是n,m的next应该是链表里n+1。由于只能遍历一次,因此我们不能先遍历一遍把m-1和n+1这两个节点先取出来,然后反转[m, n]之间的数据,必须在反转的时候就处理好这两个节点。由于反转链表会返回头节点,因此m-1的next就有着落了,反转完成,直接另m-1的next为反转后返回的头节点即可。至于和n+1处的衔接,只能在反转的时候做了。

代码如下:

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode* p = head;
for (int i = 1; i < m - 1; i++) {
p = p -> next;
}
if (m == 1) {
return reverseN(p, n - m + 1);
} else {
p -> next = reverseN(p -> next, n - m + 1);
return head;
}
}
// 从head开始,有n个节点需要被反转。这里抽出反转函数,方便各种情况的考虑。
ListNode* reverseN(ListNode* head, int n) {
// n <= 1 直接返回
if (n <= 1) return head;
ListNode *p = head;
ListNode *q = p -> next;
ListNode *r = q -> next;
for (int i = 1; i < n - 1; i++) {
q -> next = p; // 反转只在这一步
p = q; // 后面都是为了往后遍历
q = r;
r = r -> next;
}
// 最后一次反转其实还没有做,为的就是处理问题里第n+1个节点的衔接问题
q -> next = p; // 反转
head -> next = r; // 衔接第n+1个节点
return q;
}
};



2. Review

学习Spring Boot In Action 5th第1.3节。

学到的新的点是对controller的单元测试,而且这个是针对页面而不是接口。一直以来,以为只能测试接口,而不能测试页面,看来实际并不是这样。不过从测试代码来看,似乎不怎么适合测试复杂页面。代码如下:

@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
@Autowired private MockMvc mockMvc;
@Test
public void testHomePage() throws Exception {
mockMvc.perform(get("/"))
.andExpect(status().isOk()) // 验证返回状态吗
.andExpect(view().name("home")) // 验证返回的view名称
.andExpect(content().string( containsString("Welcome to..."))); // 验证返回的数据,这里只是简单验证是否包含字符串,很明显,复杂的页面不能这么操作
}
}



3. Tips

学习到了一个新的有意思的点,出自极客时间网络编程实战:

14丨UDP也可以是“已连接”?

https://time.geekbang.org/column/article/129807

看到标题,就会觉得挺有意思,实际也确实如此。该讲中的重点在于,建立udp的socket之后,执行了connect函数。一般而言,在新建udp的socket之后,都是直接往目的地址发送数据(sendto),或者监听数据(recvfrom),但是没怎么见过这个在tcp的client里会用到的connect函数。实际上这一个操作,对于内核是将udp的socket和IPv4地址进行了“绑定”,这样内核在收到该IPv4地址(ip+端口)的报文之后,就会将信息通知给对应的应用程序。

至于有状态的体现在于:

如果没有执行connect,那么在recvfrom的时候,是会一直阻塞的

如果执行了connect,那么在recvfrom的时候,当系统收到一个ICMP报文表示远端地址不可达时,会通知到应用程序,这样recvfrom就能收到错误:`recvfrom failed: Connection refused (111)`



4. Share

本次要分享的来自万维钢老师的《万万没想到》,在“别想说服我”中,有这么一句话:

人做判断是有两种机制:一种是“科学家机制”,先有证据再下结论;一种是“律师机制”,现有结论再去找证据。

每个人都爱看能印证自己已有观念的东西。我们不但不爱看,而且还会直接忽略那些不符合我们已有观念的证据。



不得不说,我们在看书或者看待别的事物的时候,总是会有一种先入为主的观念,这实际上就是代入了自己的认知。这样在看到一些符合自己认知的东西,则因为印证了我们的观念而觉得有道理,因而更有兴趣读下去,这不见得总是坏事,但是如果因此而忽略了那些不符合我们已有观念的证据,那就妨碍了我们对增长自己的见识,最终只能是井底之蛙。

用户头像

youngitachi

关注

还未添加个人签名 2018.08.22 加入

还未添加个人简介

评论

发布
暂无评论
ARTS-week-2