leetcode第一刷_Linked List Cycle II

这道题稍微有点意思,知道答案发现,呀,这么简单就能做啊。我一开始想的是,相遇之后用另一个指针怎么走,然后满足什么关系之后能推出来,其实不用这么麻烦。是很简单的数学关系,我画个图说一下。

S1代表的是链表进入环之前的长度,a代表当两个指针相遇时,走一步的指针在环里走的长度,S2代表的是环的周长,那么根据条件,相遇时,走两步的指针走的距离是走一步的两倍,我们得到公式:

(S1+a)*2 = S1+S2+a

化简一下得到

S1 = S2-a

即,环中剩下的长度刚好等于进入链表之前的长度。于是解法是:当两个指针相遇时,第一个指针回到链表头,然后两个指针都开始走一步,下次相遇的位置就是入口。

ac代码如下:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(!head||!head->next)
            return NULL;
        ListNode *a = head->next, *b = head->next->next;
        while(a!=b&&a&&b&&b->next){
            a = a->next;
            b = b->next->next;
        }
        if(a != b)
            return NULL;
        a = head;
        while(a != b){
            a = a->next;
            b = b->next;
        }
        return  a;
    }
};

leetcode第一刷_Linked List Cycle II,布布扣,bubuko.com

时间: 2024-10-03 15:01:32

leetcode第一刷_Linked List Cycle II的相关文章

leetcode第一刷_ Palindrome Partitioning II

这道题还挺复杂的,回来看了好一会儿才想起当时怎么想的..上道题刚说不要打表,这道题就用了打表.. 总的思路是这样的,从后面往前面打表,最后一个位置的最小分割一定是0,那往前呢,如果当前考虑的位置是start,并且substr(s, i)是回文的,那么如果已知i+1开始的分割次数,那么start这个位置的分割应该就是start原来的和i+1开始的分割次数加1之间的最小值.DP的思想,很直接. 但是我忽略了一个另一个开销很大的地方,那就是每次判断回文的时候.这个跟单词分割还不一样,这个范围很大.最后

leetcode第一刷_Reverse Linked List II

翻转链表绝对是终点项目,应该掌握的,这道题要求的是翻转一个区间内的节点.做法事实上非常相似,仅仅只是要注意判定開始是头的特殊情况,这样head要更新的,还有就是要把翻转之后的尾部下一个节点保存好,要么链表就断掉了.一趟就能够.遇到节点直接翻转,最后把整个翻转的链表再翻转一次,就实现了. class Solution { public: ListNode *reverseBetween(ListNode *head, int m, int n) { if(head == NULL || m==n)

leetcode第一刷_Subsets II

要求子集,有非常现成的方法.N个数,子集的个数是2^N,每个元素都有在集合中和不在集合中两种状态,这些状态用[0,pow(2,N)]中每个数来穷举,如果这个数中的第i位为1,说明当前集合中包含源数组中的第i个数. 至于有没有重复的元素,大部分有重复元素的问题,都可以借助一个vis集合,里面存放所有已经求得的集合或者其他形式的解,只有少数题目会超时,哪些问题具体的说. class Solution { public: vector<vector<int> > subsetsWithD

leetcode第一刷_Word Ladder II

注:本文仅供技术探讨, 研究,测试使用. 这个漏洞是2014年2月4日被发现的, 因为该组件试用范围非常广, 所以该漏洞的影响也非常巨大.通过特制的包含畸形header的http请求,可以导致使用该组件的应用程序进入无限循环从而耗尽CPU等资源并最终崩溃. 最近因为在修补struts1的可操纵classLoader的漏洞(struts2也有该漏洞, 不在本文讨论范围), 所以我就在我建立的struts1的项目上直接做测试,怎么创建struts1的项目不在本文讨论范围之列你可以在这里下载strut

leetcode第一刷_Unique Paths II

接着上面的问题,如果这个矩阵中有阻塞的障碍,就不能用前面的那种组合数的方法了,因为很多位置实际上是没有路的嘛. 剩下的合理解法只有dp了.跟那个求最小和的非常像,从右下角往前推算,对于一个位置(i, j),它的走法应该是(i+1, j)和(i, j+1)走法的和.对于边界条件还是有一些特殊,最后一行,从右往左,如果是0的话没有问题,等于右侧走法的个数,一旦遇到一个1,那么它以及它左边的走法都必须置成0,你可没有穿墙术. 我觉得题目明确说明了行列的个数,就是在暗示我们可以使用dp的方法,行列个数不

leetcode第一刷_Combination Sum Combination Sum II

啊啊啊啊,好怀念这种用递归保存路径然后打印出来的题目啊,好久没遇到了. 分了两种,一种是可以重复使用数组中数字的,一种是每个数字只能用一次的.其实没有多大区别,第一种每次进入递归的时候都要从头开始尝试,第二种要找一个标记的数组,把已经用到过的排除掉,就像生成全排列时的做法一样.跟我一样用引用保存中间结果的话,要注意回退的情况.第二种回退时,要把用到的那个数也恢复为可用,就完全像全排列时做的一样.破例贴两个题的代码,因为他们是在是不值得用两片文章来写. class Solution { publi

leetcode第一刷_Remove Duplicates from Sorted Array II

水题. 我之前说过包含至多几个至少几个的问题都比较难,这个题可是让我大脸了.至多可以重复一次,那就重复次数多于两次再计算重复,否则的话像普通的数据一样直接按照重复次数前移就可以了嘛.不过说归说,这种inspace的思想还是有些用处的,数组这种实现方式致命的缺点就是删除或者添加中间的元素代价太大,因为不好把握数据的最终位置.这个题是一种情况,合并两个排序好的数组也是一个例子. class Solution { public: int removeDuplicates(int A[], int n)

leetcode第一刷_Single Number II

其他出现两次,只有一个出现一次的那道题我就不更了,直接抑或,最后的结果就是那个数.为什么可以这样做呢?因为一个32位int,如果所有数都出现了两次,那么为1的那些位统计的个数一定是2的倍数,抑或之后全变成0.一个数出现了一次,它为1的那些位上,1的个数必定是奇数,抑或之后一定还是1. 我之前知道出现两次这个题的解法,但是理解的不够深,以为抑或是关键,其实不是,出现了偶数次才是关键.理解了这点,推广到出现3次上,如果所有的出现了三次,那么为1的那些位1的个数一定是三的倍数,那如果有一个数出现了一次

leetcode第一刷_Jump Game II

要求最小的步数,是不是很容易想到用dp啊? 我一开始的做法是,当找到了一个可以从它延伸到更远的位置,就把这个位置和最远位置的步数都更新一下,结果超时了.其实这样不仅是超时的,而且是错误的.因为这段距离里的很多点,其实是上一步就能到达的.其实应该更新的只有哪些新的能够到达的点,那哪些点是新的能到达的点呢?假设这次能够延伸更远的点是i,它的前进步数是A[i],上一次能够到达的最远的点是mmax,那新的能到达的点应该是(mmax, i+A[i] ]这个之间的这些位置.时间复杂度一下子变成线性的了. c