Careercup | Chapter 2

链表的题里面,快慢指针、双指针用得很多。

2.1 Write code to remove duplicates from an unsorted linked list.
FOLLOW UP
How would you solve this problem if a temporary buffer is not allowed?

2.2 Implement an algorithm to find the kth to last element of a singly linked list.

2.3 Implement an algorithm to delete a node in the middle of a singly linked list, given only access to that node.

2.4 Write code to partition a linked list around a value x, such that all nodes less than x come before alt nodes greater than or equal to x.

Leetcode上有,点

2.5 You have two numbers represented by a linked list, where each node contains a single digit. The digits are stored in reverse order, such that the 1 's digit is at the head of the list. Write a function that adds the two numbers and returns the sum as a linked list.

Leetcode上有,点
FOLLOW UP
Suppose the digits are stored in forward order. Repeat the above problem.

reverse之后求后然后再reverse结果,careercup上的做法更inefficient。

 2.6 Given a circular linked list, implement an algorithm which returns the node at the beginning of the loop.

Leetcode上有,点

2.7 Implement a function to check if a linked list is a palindrome,

naive的方法就是把list reverse一下,然后和原串比较。

更好的方法是用stack,比较前半部分还是很巧妙的。stack用来reverse也是比较直观的。注意奇偶长度的list。

递归的方法理解起来更难些。传递指针的指针,使得递归调用后,指针move到对应的镜像位置上了。这一点和Leetcode上Convert Sorted List to Binary Search Tree类似。

  1 struct ListNode {
  2     int val;
  3     ListNode* next;
  4     ListNode(int v) : val(v), next(NULL) {}
  5 };
  6 
  7 class XList {
  8 public:
  9     XList(int n) {
 10         srand(time(NULL));
 11         head = NULL;
 12         for (int i = 0; i < n; ++i) {
 13             ListNode* next = new ListNode(rand() % 1000);
 14             next->next = head;
 15             head = next;
 16         }
 17         len = n;
 18     }
 19 
 20     XList(XList &copy) {
 21         //cout << "copy construct" << endl;
 22         len = copy.size();
 23         if (len == 0) return;
 24         head = new ListNode(copy.head->val);
 25         ListNode *p = copy.head->next, * tail = head;
 26 
 27         while (p != NULL) {
 28             tail->next = new ListNode(p->val);
 29             tail = tail->next;
 30             p = p->next;    
 31         }
 32     }
 33 
 34     ~XList() {
 35         ListNode *tmp = NULL;
 36 
 37         while (head != NULL) {
 38             tmp = head->next;
 39             delete head;
 40             head = tmp;
 41         }
 42     }
 43 
 44     // 2.1(1)
 45     void removeDups() {
 46         if (head == NULL) return;
 47         map<int, bool> existed;
 48         ListNode* p = head, *pre = NULL;
 49         while (p != NULL) {
 50             if (existed[p->val]) {
 51                 pre->next = p->next;
 52                 len--;
 53                 delete p;
 54                 p = pre->next;
 55             } else {
 56                 pre = p;
 57                 existed[p->val] = true;
 58                 p = p->next;
 59             }
 60         }
 61     }
 62 
 63     //2.1(2)
 64     void removeDups2() {
 65         ListNode *p = head;
 66 
 67         while (p != NULL) {
 68             ListNode *next = p;
 69             while (next->next) {
 70                 if (next->next->val == p->val) {
 71                     ListNode *tmp = next->next;
 72                     len--;
 73                     delete next->next;
 74                     next->next = tmp->next;
 75                 } else { 
 76                     next = next->next; // only move to next in the 'else' block
 77                 }
 78             }
 79             p = p->next;
 80         }
 81     }
 82 
 83     // 2.2(1)
 84     ListNode* findKthToLast(int k) {
 85         if (head == NULL) return NULL;
 86         if (k <= 0) return NULL; // more efficient
 87         ListNode *fast = head, *slow = head;
 88         int i = 0;
 89         for (; i < k && fast; ++i) {
 90             fast = fast->next;
 91         }
 92         if (i < k) return NULL;
 93         while (fast) {
 94             slow = slow->next;
 95             fast = fast->next;
 96         }
 97         return slow;
 98     }
 99     
100     //2.2(2)
101     ListNode* findKthToLast2(int k) {
102         return recursiveFindKthToLast(head, k);
103     }
104 
105     //2.2(2)
106     ListNode* recursiveFindKthToLast(ListNode *h, int &k) {
107         if (h == NULL) {
108             return NULL;
109         }
110     
111         // should go to the end
112         ListNode *ret = recursiveFindKthToLast(h->next, k);
113         k--; 
114         if (k == 0) return h;
115         return ret;
116     }
117 
118     // 2.3
119     bool deleteNode(ListNode* node) {
120         if (node == NULL || node->next == NULL) return false; // in the middle, head is also ok, because we don't delete node itself
121 
122         ListNode *next = node->next;
123         node->val = next->val;
124         node->next = next->next;
125         len--;
126         delete next;
127         return true;
128     }
129 
130     // 2.4
131     void partition(int x) {
132         if (head == NULL) return;
133         ListNode less(0), greater(0);
134         ListNode* p = head, *p1 = &less, *p2 = &greater;
135 
136         while (p) {
137             if (p->val < x) {
138                 p1->next = p;
139                 p1 = p1->next;
140             } else {
141                 p2->next = p;
142                 p2 = p2->next;
143             }
144             p = p->next;
145         }
146 
147         p1->next = greater.next;
148         head = less.next;
149     }
150 
151     // 2.7(1)
152     bool isPalindrome() {
153         if (head == NULL) return true;
154         stack<ListNode*> st;
155         ListNode *fast = head, *slow = head;
156         while (fast && fast->next) {
157             st.push(slow);
158             slow = slow->next;
159             fast = fast->next->next;
160         }
161     
162         if (fast) slow = slow->next; // fast->next = null, odd number, skip the middle one
163 
164         while (slow) {
165             if (slow->val != st.top()->val) return false;
166             slow = slow->next;
167             st.pop();
168         }
169 
170         return true;
171     }
172 
173     // 2.7(2)
174     bool isPalindrome2() {
175         ListNode* h = head;
176         return recursiveIsPalindrome(h, len);
177     }
178 
179     bool recursiveIsPalindrome(ListNode* &h, int l) { // note that h is passed by reference
180         if (l <= 0) return true;
181         if (l == 1) {
182             h = h->next; // move, when odd
183             return true;
184         }
185         if (h == NULL) return true;
186         int v1 = h->val;
187         h = h->next;
188         if (!recursiveIsPalindrome(h, l - 2)) return false;
189         int v2 = h->val;
190         h = h->next;
191         cout << v1 << " vs. " << v2 << endl;
192         return v1 == v2;
193     }
194 
195     void print() const {
196         ListNode *p = head;
197         while (p != NULL) {
198             cout << p->val << "->";
199             p = p->next;
200         }
201         cout << "NULL(len: " << len << ")" << endl;
202     }
203 
204     int size() const {
205         return len;
206     }
207 
208     void insert(int v) {
209         len++;
210         ListNode *node = new ListNode(v);
211         node->next = head;
212         head = node;
213     }
214 private:
215     ListNode *head;
216     int len;
217 };
原文地址:https://www.cnblogs.com/linyx/p/3777817.html