1. 删除链表的节点

数据结构最简单的操作之一。但是居然耗了好久,关于链表的基本功不够!

  1. class Solution {
  2. public:
  3. ListNode* deleteNode(ListNode* head, int val) {
  4. if(head->val == val) return head->next;
  5. ListNode *pre = head, *cur = head->next;
  6. while(cur != nullptr && cur->val != val) {
  7. pre = cur;
  8. cur = cur->next;
  9. }
  10. if(cur != nullptr) pre->next = cur->next;
  11. return head;
  12. }
  13. };

2. 调整数组顺序使奇数位于偶数前面

和双指针无关,最简单的想法,创建一个vector,奇数头插,偶数尾插。但是效率极低。

  1. class Solution {
  2. private:
  3. vector<int> res;
  4. public:
  5. vector<int> exchange(vector<int>& nums) {
  6. for (int i = 0; i < nums.size(); ++i) {
  7. if (nums[i]%2==0)
  8. res.push_back(nums[i]);
  9. else
  10. res.insert(res.begin(),nums[i]);
  11. }
  12. return res;
  13. }
  14. };

执行用时:1384 ms, 在所有 C++ 提交中击败了5.35%的用户
内存消耗:19.2 MB, 在所有 C++ 提交中击败了5.04%的用户

用双指针试试:
设置两个指针,分别从左右两边开始找,左边找到第一个偶数,右边找到第一个奇数,然后交换一下。继续走直到双方碰面。

  1. class Solution {
  2. public:
  3. vector<int> exchange(vector<int> &nums) {
  4. int i = 0, j = nums.size() - 1;
  5. while (i < j) {
  6. while (nums[i] % 2 != 0 && i < j)
  7. i++;
  8. while (nums[j] % 2 == 0 && i < j)
  9. j--;
  10. swap(nums[i], nums[j]);
  11. }
  12. return nums;
  13. }
  14. };

3. 链表中倒数第 k 个节点

自己第一遍想的是先遍历一遍,然后统计出个数,然后n-k就能找到第k个节点之后的链表。但是时间复杂度太高了,根本没有用出来双指针,再思考发现用第一个指针往前走k,然后和第二个指针同步往前走,刚好第二个指针就是答案所要的头节点。

  1. class Solution {
  2. public:
  3. ListNode *getKthFromEnd(ListNode *head, int k) {
  4. if (head== nullptr)
  5. return nullptr;
  6. ListNode* curr = head;
  7. ListNode* per = head;
  8. for (int i = 1; i < k; ++i) {
  9. curr=curr->next;
  10. }
  11. while (curr->next!= nullptr){
  12. curr=curr->next;
  13. per=per->next;
  14. }
  15. return per;
  16. }
  17. };

4. 合并两个排序的链表、

自己想法是插入,以l1为基础,设置两个指针,将l2中的节点插入l1中,用了一晚上,没做出来,各种出错。先是答案错误,后面出现了空指针的问题。一晚上也没debug出来。后面看了解析,通过新建一个头节点,两个指针分别在l1和l2中进行遍历,依次加到新的头节点后。

  1. class Solution1 {
  2. public:
  3. ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
  4. ListNode *curr = l1;
  5. if (l1 == nullptr)
  6. return l2;
  7. ListNode *next = l1->next;
  8. ListNode *p2 = l2;
  9. if (l2 == nullptr)
  10. return l1;
  11. while (curr != nullptr) {
  12. if (curr->val <= p2->val) {
  13. ListNode *node = new ListNode;
  14. node->val = p2->val;
  15. node->next = next;
  16. curr->next = node;
  17. p2 = p2->next;
  18. }
  19. if (curr->val > p2->val) {
  20. ListNode *node = new ListNode;
  21. node->val = p2->val;
  22. node->next = curr;
  23. curr = node;
  24. }
  25. curr = next;
  26. if (next == nullptr) {
  27. break;
  28. }
  29. next = next->next;
  30. if (p2 == nullptr)
  31. break;
  32. }
  33. if (p2 != nullptr)
  34. curr->next = p2;
  35. return l1;
  36. }
  37. };
  38. class Solution2 {
  39. public:
  40. ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
  41. ListNode *per = l1;
  42. ListNode *curr = l1;
  43. ListNode *p2 = l2;
  44. if (l1 == nullptr) return l2;
  45. if (l2 == nullptr) return l1;
  46. while (curr != nullptr) {
  47. if (curr->val >= p2->val) {
  48. ListNode *node = new ListNode;
  49. node->val = p2->val;
  50. node->next = curr;
  51. per->next = node;
  52. p2 = p2->next;
  53. }
  54. per = curr;
  55. curr = curr->next;
  56. }
  57. if (p2 != nullptr) {
  58. curr->next = p2;
  59. }
  60. return l1;
  61. }
  62. };
  63. //正确答案
  64. class Solution3 {
  65. public:
  66. ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
  67. ListNode *res = new ListNode(0);
  68. ListNode *cur = res;
  69. while (l1 != nullptr && l2 != nullptr) {
  70. if (l1->val < l2->val) {
  71. cur->next = l1;
  72. l1 = l1->next;
  73. } else {
  74. cur->next = l2;
  75. l2 = l2->next;
  76. }
  77. cur = cur->next;
  78. }
  79. cur->next = l1 != nullptr ? l1 : l2;
  80. return res->next;
  81. }
  82. };

5. 翻转单词顺序

先去除最前面的空格,然后反转每一个单词(通过空格来控制),最后整体反转。

  1. class Solution {
  2. public:
  3. string reverseWords(string s) {
  4. string ans;
  5. int i = 0;
  6. while (i < s.size()) {
  7. //去掉空格
  8. while (i < s.size() && s[i] == ' ') i++;
  9. int j = i;
  10. //取单词
  11. while (j < s.size() && s[j] != ' ') j++;
  12. if (j > i) {
  13. string sub = s.substr(i, j - i);
  14. reverse(sub.begin(), sub.end());
  15. if (ans.size()) ans += ' ';
  16. ans += sub;
  17. }
  18. i = j;
  19. }
  20. reverse(ans.begin(), ans.end());
  21. return ans;
  22. }
  23. };
  24. class Solution1 {
  25. public:
  26. string reverseWords(string s) {
  27. int i = 0;
  28. string res;
  29. while (i < s.size()) {
  30. //去空格
  31. while (i < s.size() && s[i] == ' ')
  32. i++;
  33. //取单词
  34. int j = i;
  35. while (j < s.size() && s[j] != ' ')
  36. j++;
  37. //反转单词
  38. if (j > i) {
  39. string sub = s.substr(i, j - i);
  40. reverse(sub.begin(), sub.end());
  41. if (res.size())
  42. res += ' ';
  43. res += sub;
  44. }
  45. i = j;
  46. }
  47. //整体反转
  48. reverse(res.begin(), res.end());
  49. return res;
  50. }
  51. };

在去空格和取单词的时候,没加限定i和j都要< s.size();导致溢出。之后在res中单词直接加入空格的时候又出错,发现需要再加一个if来判断。