141. 环形链表
给定一个链表,判断链表中是否有环。
双指针方法
链表问题中的一个重要的方法叫双指针法。定义两个指针,一个叫慢指针,另一个叫快指针。通常慢指针每次向前移动一个节点,而快指针每次向前移动若干个节点。这个方法通常用于寻找链表中特定的位置。比如找到链表的中点,可以让快指针每次移动两个节点。这样当快指针到达链表末尾时,慢指针刚好在链表中间的位置。
160. 相交链表
编写一个程序,找到两个单链表相交的起始节点。
例如,下面的两个链表:
A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3
在节点 c1 开始相交。
注意:
- 如果两个链表没有交点,返回
null
. - 在返回结果后,两个链表仍须保持原有的结构。
- 可假定整个链表结构中没有循环。
- 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
基本思想是先对其两个列表,然后逐个进行比较就可以了。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { if(headA==nullptr || headB==nullptr) return nullptr; int lenA = 0, lenB = 0; length(headA, lenA); length(headB, lenB); int diff = (lenA>lenB)?lenA-lenB:lenB-lenA; while(diff>0) { if(lenA>lenB) headA = headA->next; else headB = headB->next; --diff; } while(headA!=nullptr && headB!=nullptr) { if(headA->val == headB->val) return headA; headA = headA->next; headB = headB->next; } return nullptr; } void length(ListNode *head, int &len) { while(head!=nullptr) { len++; head = head->next; } } };
83. 删除排序链表中的重复元素
示例 1:
输入: 1->1->2 输出: 1->2
示例 2:
输入: 1->1->2->3->3 输出: 1->2->3
基本思想就是两个指针,一个指向第一个,一个指向第二个,如果相等就删除,如果不相等就后移动
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* deleteDuplicates(ListNode* head) { if(head == nullptr || head->next==nullptr) return head; ListNode *first = head; ListNode *second = head->next; while(second != nullptr) { if(first->val == second->val) { first->next = second->next; second = second->next; } else { first = second; second = second->next; } } return head; } };
82. 删除排序链表中的重复元素 II
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
示例 1:
输入: 1->2->3->3->4->4->5 输出: 1->2->5
示例 2:
输入: 1->1->1->2->3 输出: 2->3
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* deleteDuplicates(ListNode* head) { if(head == nullptr || head->next==nullptr) return head; //用一个dummy节点来当做head的prev ListNode dummy(0); dummy.next = head; ListNode *prev = &dummy; ListNode *first = prev->next; ListNode *second = first->next; // 用来表明状态的变化,从不相等,变成了相等,然后在根据这个状态变化来针对性的进行修改 bool flag = false; while(second != nullptr) { if(first->val == second->val) { first->next = second->next; second = second->next; flag = true; } else { if(flag) { prev->next = second; first = second; second = second->next; flag = false; continue; } prev = first; first = second; second = second->next; } } // 如果flag为真,表明最后一个也是重复的元素,需要单独考虑,因为这个时候已经退出循环了 if(flag) { prev->next = nullptr; } return dummy.next; } };