Tag Archives: 链表

LeetCode Insertion Sort List

147. Insertion Sort List

Sort a linked list using insertion sort.


A graphical example of insertion sort. The partial sorted list (black) initially contains only the first element in the list.
With each iteration one element (red) is removed from the input data and inserted in-place into the sorted list
 

Algorithm of Insertion Sort:

  1. Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list.
  2. At each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there.
  3. It repeats until no input elements remain.


Example 1:

Input: 4->2->1->3
Output: 1->2->3->4

Example 2:

Input: -1->5->3->4->0
Output: -1->0->3->4->5

对一个链表进行插入排序。 简单题,每次从原链表中断一个节点下来,然后在新的有序链表中线性查找插入的位置。这里有个技巧,有可能链表的第一个节点很大,后续节点需要插入表头;也可能后续节点很大,需要插入表尾;还可能是不大不小,插入中间。情况比较多,为了方便统一代码形式,可以在新的有序链表的表头插入一个INT_MIN的最小节点,这样所有代码都统一了,也不容易出错。 完整代码如下:

class Solution {
public:
    ListNode* insertionSortList(ListNode* head)
    {
        if (head == NULL || head->next == NULL)
            return head;
        ListNode* newHead = new ListNode(INT_MIN);
        newHead->next = head;
        head = head->next;
        newHead->next->next = NULL;
        while (head) {
            ListNode *insertPos = newHead->next, *pre = newHead;
            while (insertPos && insertPos->val < head->val) {
                insertPos = insertPos->next;
                pre = pre->next;
            }
            ListNode* tmp = head;
            head = head->next;
            tmp->next = insertPos;
            pre->next = tmp;
        }
        return newHead->next;
    }
};

本代码提交AC,用时59MS。

二刷。需要注意如果测试数据中含有INT_MIN的情况:

class Solution {
public:
	ListNode* insertionSortList(ListNode* head) {
		if (head == NULL || head->next == NULL)return head;
		ListNode *dummy = new ListNode(INT_MIN);
		ListNode *l1 = head, *l2 = head;
		while (l1 != NULL) {
			l2 = l1->next;

			ListNode *l3 = dummy, *l3_pre = dummy;
			while (l3 != NULL && l1->val > l3->val) {
				l3_pre = l3;
				l3 = l3->next;
			}
			if (l1->val == INT_MIN) {
				l1->next = dummy->next;
				dummy->next = l1;
			}
			else {
				l1->next = l3;
				l3_pre->next = l1;
			}

			l1 = l2;
		}
		return dummy->next;
	}
};

本代码提交AC,用时48MS。

LeetCode Intersection of Two Linked Lists

160. Intersection of Two Linked Lists

Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:

begin to intersect at node c1.

Example 1:

Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
Output: Reference of the node with value = 8
Input Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,0,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.

Example 2:

Input: intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
Output: Reference of the node with value = 2
Input Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [0,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B.

Example 3:

Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
Output: null
Input Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values.
Explanation: The two lists do not intersect, so return null.

Notes:

  • If the two linked lists have no intersection at all, return null.
  • The linked lists must retain their original structure after the function returns.
  • You may assume there are no cycles anywhere in the entire linked structure.
  • Your code should preferably run in O(n) time and use only O(1) memory.

给定两个链表,如果这两个链表在某个点相交,并且此后合并为一个链表,要找出这个交点;如果不想交,返回NULL。 简单的方法是,如果两个链表相交,比如题图在c1相交,则对于两个链表,从相交点往后长度是一样的,所以我们可以先求出两个链表的长度,假设长度差是delta,则较长链表先前进delta步,此时长短链表的往后的路都是一样长了,这样两个链表一起走,如果发现有相等的节点,则是相交节点,否则两个链表不相交。 本思路代码如下:

class Solution {
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB)
    {
        int len1 = 0, len2 = 0;
        ListNode *h1 = headA, *h2 = headB;
        while (h1) {
            ++len1;
            h1 = h1->next;
        }
        while (h2) {
            ++len2;
            h2 = h2->next;
        }
        h1 = headA;
        h2 = headB;
        if (len1 > len2) {
            while (len1 > len2) {
                h1 = h1->next;
                –len1;
            }
        }
        else if (len2 > len1) {
            while (len2 > len1) {
                h2 = h2->next;
                –len2;
            }
        }
        while (h1 && h2 && h1 != h2) {
            h1 = h1->next;
            h2 = h2->next;
        }
        if (!h1 || !h2)
            return NULL;
        else
            return h1;
    }
};

本代码提交AC,用时39MS。
还有一种思路很巧妙,参考:http://www.cnblogs.com/yuzhangcmu/p/4128794.html
具体是这样的,比如题目中的例子,假设指针pA和pB分别指向A,B两个链表,两个指针同时不断的一步一步走,当pA走到结尾时,pA指向B链表表头开始走,同理当pB走到结尾时,pB指向A链表表头开始走。不断的走,当pA和pB指向同一个节点时,就是那个相交的节点。这个很巧妙呀,当pA和pB走到相交点时,他们走过的路程其实是相等的,比如题目中,他们都走了9个节点后相遇了。
代码如下:

class Solution {
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB)
    {
        if (headA == NULL || headB == NULL)
            return NULL;
        ListNode *h1 = headA, *h2 = headB;
        ListNode *tail1 = NULL, *tail2 = NULL;
        while (true) {
            if (h1 == NULL)
                h1 = headB;
            if (h2 == NULL)
                h2 = headA;
            if (h1->next == NULL)
                tail1 = h1;
            if (h2->next == NULL)
                tail2 = h2;
            if (tail1 != NULL && tail2 != NULL && tail1 != tail2)
                return NULL;
            if (h1 == h2)
                return h1;
            h1 = h1->next;
            h2 = h2->next;
        }
    }
};

本代码提交AC,用时36MS。

三刷。同样的思路:

class Solution {
public:
	ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
		if (headA == NULL || headB == NULL)return NULL;
		ListNode *la = headA, *lb = headB;
		bool la_changed = false, lb_changed = false;
		while (la != lb) {
			la = la->next;
			lb = lb->next;
			if (la == NULL) {
				if (la_changed)return NULL;
				else {
					la = headB;
					la_changed = true;
				}
			}
			if (lb == NULL) {
				if (lb_changed)return NULL;
				else {
					lb = headA;
					lb_changed = true;
				}
			}
		}
		return la;
	}
};

本代码提交AC,用时68MS。

LeetCode Flatten Binary Tree to Linked List

114. Flatten Binary Tree to Linked List

Given a binary tree, flatten it to a linked list in-place.

For example, given the following tree:

    1
   / \
  2   5
 / \   \
3   4   6

The flattened tree should look like:

1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

把一棵二叉树展开成一个链表,链表还是借助树的数据结构,只不过是借用了树的右孩子指针作为链表的指针。 仔细观察发现新的链表的顺序和树的先序遍历的顺序一致,如果能使用额外的空间,则先序遍历后把节点存到数组中,然后依次链接起来。 如果不使用额外空间,则只能想办法在DFS时就建立好链接关系。先序遍历的顺序是根左右,但是这题为了方便,我们先对右孩子建立链表,然后把右孩子接到父亲的左孩子的最右下角的节点上。比如上图中,我们建立好5->6的链表之后,需要把它接到4号节点的右边。

         1
        /
       2
      / \
     3   4
          \
           5
            \
             6

所以针对右孩子,我们需要根据父节点找到父节点的左子树的最右下角的节点。但是针对左孩子时,因为此时右孩子已经建立好链表并且接到了左孩子正确的位置上,所以只需要把左孩子接到父亲的右孩子位置,并把原来的左孩子置空,下图就是把上图1的左子树放到了右边,左边置为空。

   1
     \
       2
      / \
     3   4
          \
           5
            \
             6

完整代码如下:

class Solution2 {
public:
    void dfs(TreeNode* par, TreeNode* cur)
    {
        if (cur == NULL)
            return;
        if (par) {
            if (cur == par->right) {
                if (par->left) {
                    TreeNode* tmp = par->left;
                    while (tmp->right)
                        tmp = tmp->right;
                    tmp->right = cur;
                    par->right = NULL;
                }
            }
            else {
                par->right = cur;
                par->left = NULL;
            }
        }
        if (cur->right)
            dfs(cur, cur->right);
        if (cur->left)
            dfs(cur, cur->left);
    }
    void flatten(TreeNode* root) { dfs(NULL, root); }
};

本代码提交AC,用时6MS。
还有一种思路比这简单,上面的解法需要while循环查找左兄弟的最右下角的节点,如果我们在DFS中直接返回尾节点,就不需要while查找了。
假设某节点的左右子树T(root->left)和T(root->right)已经flatten成linked list了:
1
/    \
2     5
\       \
3      6 <- rightTail
\
4  <- leftTail
如何将root、T(root->left)、T(root->right) flatten成一整个linked list?显而易见:
leftTail->right = root->right;
root->right = root->left;
root->left = NULL;
这里需要用到已经flatten的linked list的尾部元素leftTail, rightTail。所以递归返回值应该是生成的整个linked list的尾部。
代码如下:

class Solution {
public:
    TreeNode* dfs(TreeNode* root)
    {
        if (!root)
            return NULL;
        TreeNode* leftTail = dfs(root->left);
        TreeNode* rightTail = dfs(root->right);
        if (root->left) {
            leftTail->right = root->right;
            root->right = root->left;
            root->left = NULL;
        }
        if (rightTail)
            return rightTail;
        if (leftTail)
            return leftTail;
        return root;
    }
    void flatten(TreeNode* root) { dfs(root); }
};

本代码提交AC,用时6MS。

LeetCode Odd Even Linked List

LeetCode Odd Even Linked List Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes. You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity. Example: Given 1->2->3->4->5->NULL, return 1->3->5->2->4->NULL. Note: The relative order inside both the even and odd groups should remain as it was in the input. The first node is considered odd, the second node even and so on …


链表题,要求把链表中的奇数位节点连接起来,偶数位节点也连接起来,最后这两个链表连接起来。要求O(1)的空间复杂度和O(n)的时间复杂度。 因为奇数链表和偶数链表都是从原链表中隔一个取一个,立马联想到快慢指针,在这个题里,我们设置两个快指针fast1和fast2,分别指向奇数节点和偶数节点,然后分别取下来,接到odd和even链表中。最后把odd的tail指向even的head就搞定了。符合O(1)空间复杂度和O(n)时间复杂度。 完整代码如下: [cpp] class Solution { public: ListNode* oddEvenList(ListNode* head) { if (head == NULL)return head; ListNode *odd = new ListNode(0), *even = new ListNode(0); ListNode *otail = odd, *etail = even; ListNode *fast1 = head, *fast2 = head->next; while (fast1 || fast2) { otail->next = fast1; etail->next = fast2; if (otail)otail = otail->next; if (etail)etail = etail->next; if (fast2)fast1 = fast2->next; else fast1 = NULL; if (fast1)fast2 = fast1->next; else fast2 = NULL; } otail->next = even->next; return odd->next; } }; [/cpp] 本代码提交AC,用时16MS。 二刷。其实不用快慢指针,直接根据奇偶性就可以了,更简洁的代码如下: [cpp] class Solution { public: ListNode* oddEvenList(ListNode* head) { ListNode *odd = new ListNode(0), *even = new ListNode(0); int cnt = 1; ListNode *cur = head, *otail = odd, *etail = even; while(cur) { if(cnt & 1) { otail->next = cur; otail = otail->next; } else { etail->next =cur; etail = etail->next; } cur = cur->next; ++cnt; } otail->next = even->next; etail->next = NULL; // caution!!! return odd->next; } }; [/cpp] 本代码提交AC,用时19MS。]]>

LeetCode Add Two Numbers II

LeetCode Add Two Numbers II You are given two non-empty linked lists representing two non-negative integers. The most significant digit comes first and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself. Follow up: What if you cannot modify the input lists? In other words, reversing the lists is not allowed. Example:

Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 8 -> 0 -> 7

有两个数字链表,分别存储了两个整数,要求把这两个整数加起来。和LeetCode Add Two Numbers的区别是,之前的链表最低位在表头,我们正常加法也是从低位到高位,所以之前的题可以直接从表头开始加。但是这个题稍有不同,最低位在表尾,表头是最高位,所以必须先跑到链表尾才能做加法。一种方法是我们可以先把链表逆序,这样就可以用之前的解法了,但是题目中说不能修改原链表,所以不能用这种解法。 那么怎样获取到表尾的数据进行加法呢,我们可以把两个链表压入两个堆栈,因为堆栈是后进先出,所以再次从栈顶取数据做加法的时候就是从低位到高位的加了。 完整代码如下: [cpp] class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { stack<int> s1, s2; while (l1) { s1.push(l1->val); l1 = l1->next; } while (l2) { s2.push(l2->val); l2 = l2->next; } ListNode* ans = new ListNode(1); // 预设好的最高位进位:-) int sum = 0; while (!s1.empty() || !s2.empty()) { if (!s1.empty()) { sum += s1.top(); s1.pop(); } if (!s2.empty()) { sum += s2.top(); s2.pop(); } ListNode* tmp = new ListNode(sum%10); tmp->next = ans->next; ans->next = tmp; sum /= 10; // 下一次的进位 } if (sum)return ans; else return ans->next; } }; [/cpp] 本代码提交AC,用时55MS。 代码中有两个地方解释一下,一般链表的题都会在结果链表中加一个没用的头结点,一般是0,但是因为最终的加法结果可能进位,所以把表头的值定为1,如果有进位,这个1也可以用上,如果没进位,就返回1的next。另一个就是我们没有单独定义add1、add2和carry,而是只用一个sum变量搞定了,sum%10相当于进位之后的结果,sum/10相当于进位。]]>

LeetCode Linked List Cycle II

142. Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

Note: Do not modify the linked list.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.

Follow-up:
Can you solve it without using extra space?


本题在LeetCode Linked List Cycle的基础上更进一步,需要求出链表中环的起点位置。 接上一题,相遇位置在Z,此时如果令slower=head,然后slower和faster都以相同的速度走a步,则slower刚好能到环的起点位置Y,那么faster会在哪里呢。 上一题推出来相遇的时候有:a+b=(n-2m)c,如果faster在相遇点走a步,则相当于走了a=(n-2m)c-b,(n-2m)c相当于绕圈n-2m次,(n-2m)c-b的意思就是在z点绕圈n-2m次的基础上,退回b步,看图,退回b步正好到达了环的起点Y。 所以快慢指针再走a步之后,正好在环的起点相遇了! 于是本题的思路就是:先用上一题的方法找到相遇位置,然后slower回到head节点,slower和faster都再次单步走,再次相遇时,就是环的起点。 完整代码如下:

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

本代码提交AC,用时13MS。

LeetCode Linked List Cycle

141. Linked List Cycle

Given a linked list, determine if it has a cycle in it.

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.

Follow up:

Can you solve it using O(1) (i.e. constant) memory?


本题要判断一个链表中是否包含环,注意这里的环可能是局部的环,并不一定是链表头尾相连那种环,比如下图。 解题思路是使用快慢指针,如果链表中有环,则快慢指针一定会在某处相遇,证明请看这篇博客,我试着重述一遍: 首先请看示意图,假设链表起点为X,环的起点为Y,环的总长度为c,快慢指针在环的Z点相遇,YZ=b,XY=a。则有

a+b+mc=s—(1)

a+b+nc=2s—-(2)

(1)和(2)式分别为慢快指针的等式,其中s表示慢指针走过的节点,则快指针走过两倍的s,m和n分别为慢快指针绕圈的圈数,显然n>m。 把(1)代入(2)得到a+b=(n-2m)c。假设真的存在环,则a和c是链表的固有值,是已知量,所以如果能找到m,n,b的一组解,则说明假设成立,真的存在环。 令m=0,n=a,b=ac-a,则这一组解是满足上面的方程(1)和(2)的,也满足n>m。因为环的长度>1,所以b也是大于0的。既然找到一组解,说明假设成立,即存在环。也就是说,我们可以用这种方法判断环是否存在。 完整代码如下:

class Solution {
public:
    bool hasCycle(ListNode* head)
    {
        if (head == NULL || head->next == NULL)
            return false;
        ListNode *faster = head, *slower = head;
        while (faster->next != NULL && faster->next->next != NULL) {
            faster = faster->next->next;
            slower = slower->next;
            if (faster == slower)
                return true;
        }
        return false;
    }
};

本代码提交AC,用时9MS。
证明参考:
https://stackoverflow.com/a/6110767/2468587
https://math.stackexchange.com/a/913529/161019

LeetCode Palindrome Linked List

234. Palindrome Linked List

Given a singly linked list, determine if it is a palindrome.

Example 1:

Input: 1->2
Output: false

Example 2:

Input: 1->2->2->1
Output: true

Follow up:
Could you do it in O(n) time and O(1) space? 234. Palindrome Linked List


本题要判断一个单向链表是否为回文链表。之前LeetCode Valid Palindrome判断的是数组,可以直接访问数组的头尾元素,但是链表不可以随机访问。 仔细观察一下,下面两条回文链表:

  1. 1->2->3->4->5->4->3->2->1
  2. 1->2->3->4->4->3->2->1

判断回文链表最原始的方法是从左往右读一遍和从右往左读一遍,如果读得的结果一样就是回文,比如第1条回文,从左往右是123454321,从右往左也是123454321,所以它是回文。 但是其实我们可以不用完整读一遍,我们只读一半就可以了,比如回文1的前半部分是1234,后半部分是4321,前半部分顺着读和后半部分倒着读都是1234,这样就足以说明是回文串了。 紧接着,对于链表,我们就有这样一种解题思路:首先找到链表的中间节点,然后把后半部分链表逆序,最后看看逆序的后半部分和顺序的前半部分是否相同。 找链表的中间节点的常规思路就是快慢指针,这个在很多题中都用到了,需要指出的是,回文链表有两种情况,一种是形如1的奇数个元素,另一种是形如2的偶数个元素。如果用快慢指针找中点,1能找到真正的中点5,2能找到前一个中点4,所以我们判断回文的时候,只需要把中点后面的链表逆序,然后只比较后半部分的链表元素。比如1的情况,逆序后半部分之后得到1->2->3->4,那么前半部分也只需要比较1->2->3->4,不需要比较5,因为这是奇数链表的中点,前后链表共享的元素;2的情况,逆序后半部分之后得到1->2->3->4,前半部分也是1->2->3->4,偶数长度的情况就会把中间的两个元素分到前后两部分。 完整代码如下:

class Solution {
public:
    bool isPalindrome(ListNode* head)
    {
        if (head == NULL || head->next == NULL)
            return true;
        ListNode *faster = head, *slower = head;
        while (faster->next != NULL && faster->next->next != NULL) {
            faster = faster->next->next;
            slower = slower->next;
        } //bool odd = faster->next == NULL ? true : false; // 链表长度是否为奇数
        ListNode *head2 = slower, *prior = slower->next, *tail;
        head2->next = NULL;
        while (prior != NULL) { // 逆序后半段链表
            tail = prior->next;
            prior->next = head2->next;
            head2->next = prior;
            prior = tail;
        }
        head2 = head2->next;
        while (head2 != NULL) {
            if (head->val != head2->val)
                return false;
            head = head->next;
            head2 = head2->next;
        }
        return true;
    }
};

本代码提交AC,用时25MS。

二刷。同样的思路:

class Solution {
public:
	bool isPalindrome(ListNode* head) {
		if (head == NULL || head->next == NULL)return true;
		// 快慢指针
		ListNode *fast = head, *slow = head;
		while (fast != NULL && fast->next != NULL) {
			fast = fast->next->next;
			slow = slow->next;
		}
		// 逆序后半段
		ListNode *dummy = new ListNode(0);
		ListNode *par = slow, *child = slow->next;
		while (par != NULL) {
			child = par->next;
			par->next = dummy->next;
			dummy->next = par;
			par = child;
		}
		// 判断是否相等
		slow = head;
		fast = dummy->next;
		while (fast != NULL) {
			if (slow->val != fast->val)return false;
			slow = slow->next;
			fast = fast->next;
		}
		return true;
	}
};

本代码提交AC,用时28MS。

LeetCode Partition List

86. Partition List

Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.

You should preserve the original relative order of the nodes in each of the two partitions.

Example:

Input: head = 1->4->3->2->5->2, x = 3
Output: 1->2->2->4->3->5

本题要求把链表中小于某个数的节点移到大于等于某个数的节点前面,要求两个部分中的节点的相对顺序不变。 思路很简单,维护两个链表,一个是小于x的,另一个是大于等于x的,然后遍历原链表,分别把小于和大于等于x的节点接到对应的链表上。最后记得把第一个链表的尾部连到第二个链表的头部,然后第二个链表的尾节点置空。 完整代码如下:

class Solution {
public:
    ListNode* partition(ListNode* head, int x)
    {
        ListNode *head1 = new ListNode(0), *head2 = new ListNode(0);
        ListNode *prior1 = head1, *prior2 = head2;
        while (head != NULL) {
            if (head->val < x) {
                prior1->next = head;
                prior1 = prior1->next;
            }
            else {
                prior2->next = head;
                prior2 = prior2->next;
            }
            head = head->next;
        }
        prior2->next = NULL;
        prior1->next = head2->next;
        return head1->next;
    }
};

本代码提交AC,用时6MS。

LeetCode Delete Node in a Linked List

237. Delete Node in a Linked List

Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.

Given linked list — head = [4,5,1,9], which looks like following:

Example 1:

Input: head = [4,5,1,9], node = 5
Output: [4,1,9]
Explanation: You are given the second node with value 5, the linked list should become 4 -> 1 -> 9 after calling your function.

Example 2:

Input: head = [4,5,1,9], node = 1
Output: [4,5,9]
Explanation: You are given the third node with value 1, the linked list should become 4 -> 5 -> 9 after calling your function.

Note:

  • The linked list will have at least two elements.
  • All of the nodes’ values will be unique.
  • The given node will not be the tail and it will always be a valid node of the linked list.
  • Do not return anything from your function.237. Delete Node in a Linked List

删掉单向链表中的某个指定的节点,这个节点不是尾节点。 本科面试的时候遇到过这个题,当时好像没做出来…因为要删掉某个节点,肯定要知道其前驱节点prior,然后prior->next=prior->next->next。但是这一题只让访问当前节点,单向链表又无法获取其前驱节点,所以当时想了很久都没解出来。 今天灵光一闪,只能访问当前节点,又得不到其前驱节点,唯一可以知道的是其后继节点,所以我们可以不用真正的删掉当前节点,可以把后继节点的值赋给当前节点,然后删掉后继节点! 想到这一点就很简单了,也许这也是为什么题目说不包括尾节点,因为删掉尾节点不能用上述方法,只能用其前驱节点删除。 完整代码如下:

class Solution {
public:
    void deleteNode(ListNode* node)
    {
        node->val = node->next->val;
        ListNode *no_use=node->next;
        node->next = node->next->next;
        delete no_use;
    }
};

本代码提交AC,用时13MS。