Day-01-链表 Leetcode-206, 92, 160, 141, 86, 138, 21, 23

目录

例一:LeetCode206

例二:LeetCode92

例三:LeetCode160

例四:LeetCode141

例五:LeetCode86

例六:LeetCode138

例七:LeetCode21

例八:LeetCode23


例一:LeetCode206

//已知链表头节点指针head,将链表逆序,不可申请额外空间
#include <stdio.h>
struct ListNode {
       int val;
       ListNode* next;
       ListNode(int x) :val(x), next(NULL) {}
};
class Solution {
public:
       ListNode* reverseList(ListNode* head) {
              ListNode* new_head = NULL;
              while (head) {
                      ListNode* next = head->next;
                      head->next = new_head;
                      new_head = head;
                      head = next;
              }
              return new_head;
       }
};
int main() {
       ListNode a(1);
       ListNode b(2);
       ListNode c(3);
       ListNode d(4);
       ListNode e(5);
       a.next = &b;
       b.next = &c;
       c.next = &d;
       d.next = &e;
       Solution solve;
       ListNode* head = &a;
       printf("Before reverse:\n");
       while (head) {
              printf("%d\n", head->val);
              head = head->next;
       }
       head = solve.reverseList(&a);
       printf("After reverse:\n");
       while (head) {
              printf("%d\n", head -> val);
              head = head->next;
       }
       return 0;
}

例二:LeetCode92

//已知链表头节点指针head,将链表从位置m到n逆序,不能申请额外空间
#include <stdio.h>
struct ListNode {
       int val;
       ListNode* next;
       ListNode(int x) :val(x), next(NULL) {};
};
class Solution {
public:
       ListNode* reverseBetween(ListNode* head, int m, int n) {
              int change_len = n - m + 1;//计算需要逆置的节点个数
              ListNode* pre_head = NULL;//初始化开始逆置的节点的前驱
              ListNode* result = head;//最终转化后的链表的头节点,非特殊情况即为head
              while (head && --m) {//head向前移动m-1个位置
                      pre_head = head;
                      head = head->next;
              }
              ListNode* modify_list_tall = head;//将modify_list_tall指向当前的head,即逆置后的链表尾
              ListNode* new_head = NULL;
              while (head && change_len) {//逆置change_len个节点
                      ListNode* next = head->next;
                      head->next = new_head;
                      new_head = head;
                      head = next;
                      change_len--;
              }
              modify_list_tall->next = head;
              if (pre_head) {
                      pre_head->next = new_head;
              }
              else {
                      result = new_head;//如果head不为空,说明不是从第一个节点开始逆置的m>1
              }
              return result;
       }
};
int main() {
       ListNode a(1);
       ListNode b(2);
       ListNode c(3);
       ListNode d(4);
       ListNode e(5);
       a.next = &b;
       b.next = &c;
       c.next = &d;
       d.next = &e;
       Solution solve;
       ListNode* head = solve.reverseBetween(&a, 2, 4);
       while (head) {
              printf("%d\n", head->val);
              head = head->next;
       }
       return 0;
}

例三:LeetCode160

 

//已知链表A的头节点指针headA,链表B的头节点指针headB,两个链表相交,求两链表交点对应的节点。
#include <stdio.h>
struct ListNode {
       int val;
       ListNode* next;
       ListNode(int x) : val(x), next(NULL) {};
};
//时间nlogn 空间O(n)
// class Solution{
// public:
//     ListNode* getIntersectionNode(ListNode* headA,ListNode* headB){
//            std::set<ListNode*> node_set;
//            while(headA){
//                    node_set.insert(headA);
//                    headA=headA->next;
//            }
//            while(headB){
//                    if(node_set.find(headB!=node_set.end())){
//                           return headB;
//                    }
//                    headB=headB->next;
//            }
//            return NULL
//     }
// };
//
//时间O(n) 空间O(1)
int get_list_length(ListNode* head) {
       int len = 0;
       while (head) {
              len++;
              head = head->next;
       }
       return len;
}
ListNode* forward_long_list(int long_len, int short_len, ListNode* head) {
       int delta = long_len - short_len;
       while (head && delta) {
              head = head->next;
              delta--;
       }
       return head;
}
class Solution {
public:
       ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
              int list_A_len = get_list_length(headA);
              int list_B_len = get_list_length(headB);
              if (list_A_len > list_B_len) {
                      headA = forward_long_list(list_A_len, list_B_len, headA);
              }
              else {
                      headB = forward_long_list(list_B_len, list_A_len, headB);
              }
              while (headA && headB) {
                      if (headA == headB) {
                             return headA;
                      }
                      headA = headA->next;
                      headB = headB->next;
              }
              return NULL;
       }
};
int main() {
       ListNode a1(1);
       ListNode a2(2);
       ListNode b1(3);
       ListNode b2(4);
       ListNode b3(5);
       ListNode c1(6);
       ListNode c2(7);
       ListNode c3(8);
       a1.next = &a2;
       a2.next = &c1;
       c1.next = &c2;
       c2.next = &c3;
       b1.next = &b2;
       b2.next = &b3;
       b3.next = &c1;
       Solution solve;
       ListNode* result = solve.getIntersectionNode(&a1, &b1);
       printf("%d\n", result->val);
       return 0;
}

例四:LeetCode141

//已知链表中可能存在环,若有环返回环起始节点,否则返回NULL
#include <stdio.h>
struct ListNode {
       int val;
       ListNode* next;
       ListNode(int x) : val(x), next(NULL) {}
};
// class Solution{
// public:
//     ListNode* detectCycle (ListNode* head){
//            std::set<ListNode*> node_set;
//            while(head){
//                    if(node_set.find(head) != node_set.end()){
//                           return head;
//                    }
//                    node_set.insert(head);
//                    head = head->next;
//            }
//            return NULL;
//     }
// };
//
class Solution {
public:
       ListNode* detectCycle(ListNode* head) {
              ListNode* fast = head;
              ListNode* slow = head;
              ListNode* meet = NULL;//相遇节点
              while (fast) {
                      slow = slow->next;
                      fast = fast->next;
                      if (!fast) {
                             return NULL;
                      }
                      fast = fast->next;
                      if (fast == slow) {
                             meet = fast;
                             break;
                      }
              }
              if (meet == NULL) {
                      return NULL;
              }
              while (head && meet) {
                      if (meet == head) {
                             return head;
                      }
                      head = head->next;
                      meet = meet->next;
              }
              return NULL;
       }
};
int main() {
       ListNode a(1);
       ListNode b(2);
       ListNode c(3);
       ListNode d(4);
       ListNode e(5);
       ListNode f(6);
       ListNode g(7);
       a.next = &b;
       b.next = &c;
       c.next = &d;
       d.next = &e;
       e.next = &f;
       f.next = &g;
       g.next = &c;
       Solution solve;
       ListNode* node = solve.detectCycle(&a);
       if (node) {
              printf("%d\n", node->val);
       }
       else {
              printf("NULL\n");
       }
       return 0;
}

例五:LeetCode86

//已知链表的头指针head和数值X,将所有小于X的节点放在大于或等于X的节点前,且保持这些节点原来的相对位置。
#include <stdio.h>
struct ListNode       {
       int val;
       ListNode* next;
       ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
       ListNode* partition(ListNode* head, int x) {
              ListNode less_head(0);
              ListNode more_head(0);
              ListNode* less_ptr = &less_head;
              ListNode* more_ptr = &more_head;
              while (head) {
                      if (head->val < x) {
                             less_ptr->next = head;
                             less_ptr = head;
                      }
                      else {
                             more_ptr->next = head;
                             more_ptr = head;
                      }
                      head = head->next;
              }
              less_ptr->next = more_head.next;
              more_ptr->next = NULL;
              return less_head.next;
       }
};
int main() {
       ListNode a(1);
       ListNode b(4);
       ListNode c(3);
       ListNode d(2);
       ListNode e(5);
       ListNode f(2);
       a.next = &b;
       b.next = &c;
       c.next = &d;
       d.next = &e;
       e.next = &f;
       Solution solve;
       ListNode* head = solve.partition(&a, 3);
       while (head) {
              printf("%d\n", head->val);
              head = head->next;
       }
       return 0;
}

例六:LeetCode138

//已知一个复杂的链表,节点中有一个指向本链表任意某个节点的随机指针(也可以为空),求这个链表的深度拷贝。
//深度拷贝:
#include <stdio.h>
#include <map>
#include <vector>

struct Node {
	int val;
	Node* next, * random;
	Node(int _x, Node *_next, Node *_random) : val(_x), next(_next), random(_random) {}
};

//map<key,val> name; 通过节点的地址,得知是第几个节点 
//int main() {
//	std::map<RandomListNode*, int> node_map;
//	RandomListNode a(5);
//	RandomListNode b(3);
//	RandomListNode c(6);
//
//	a.next = &b;
//	b.next = &c;
//	a.random = &c;
//	b.random = &a;
//	c.random = &c;
//	node_map[&a] = 1; 
//	node_map[&b] = 2;
//	node_map[&c] = 3;
//	printf("a.random id = %d\n", node_map[a.random]);
//	printf("b.random id = %d\n", node_map[b.random]);
//	printf("c.random id = %d\n", node_map[c.random]);
//	return 0;
//}


class Solution {
public:
	Node* copyRandomList(Node* head) {
		std::map<Node*, int> node_map;//利用map根据地址得到是第几个节点
		std::vector<Node*> node_vec;//使用vector存储新链表的节点
		Node* ptr = head;
		int i = 0;
		while (ptr) {
			node_vec.push_back(new Node(ptr->val, NULL, NULL));
			node_map[ptr] = i;
			ptr = ptr->next;
			i++;
		}
		node_vec.push_back(0);//为了让51行的操作到最后一个节点时任然一致
		ptr = head;
		i = 0;
		while (ptr) {
			node_vec[i]->next = node_vec[i + 1];
			if (ptr->random) {
				int id = node_map[ptr->random];
				node_vec[i]->random = node_vec[id];
			}
			ptr = ptr->next;
			i++;
		}
		return node_vec[0];
	}
};

int main() {
	Node a(1, NULL, NULL);
	Node b(2, NULL, NULL);
	Node c(3, NULL, NULL);
	Node d(4, NULL, NULL);
	Node e(5, NULL, NULL);
	a.next = &b;
	b.next = &c;
	c.next = &d;
	d.next = &e;
	a.random = &c;
	b.random = &d;
	c.random = &c;
	e.random = &d;
	Solution solve;
	Node* head = solve.copyRandomList(&a);
	while (head) {
		printf("label = %d ", head->val);
		if (head->random) {
			printf("rand = %d\n", head->random->val);
		}
		else {
			printf("rand = NULL\n");
		}
		head = head->next;
	}
	return 0;
}

例七:LeetCode21

//已知两个已排序链表的头节点指针l1和l2,将这两个链表合并,合并后任然为有序的,并返回头节点。

#include <stdio.h>

struct ListNode {
	int val;
	ListNode* next;
	ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
	ListNode* mergeTwoLists(ListNode* L1, ListNode* L2) {
		ListNode temp_head(0);
		ListNode* ptr = &temp_head;
		while (L1 && L2) {
			if (L1->val < L2->val) {
				ptr->next = L1;
				L1 = L1->next;
			}
			else {
				ptr->next = L2;
				L2 = L2->next;
			}
			ptr = ptr->next;
		}
		if (L1) {
			ptr->next = L1;
		}
		if (L2) {
			ptr->next = L2;
		}
		return temp_head.next;
	}
};

int main() {
	ListNode a(1);
	ListNode b(4);
	ListNode c(6);
	ListNode d(0);
	ListNode e(5);
	ListNode f(7);
	a.next = &b;
	b.next = &c;
	d.next = &e;
	e.next = &f;
	Solution solve;
	ListNode* head = solve.mergeTwoLists(&a, &d);
	while (head) {
		printf("%d\n", head->val);
		head = head->next;
	}
	return 0;
}

例八:LeetCode23

 

//已知k个已排序链表的头节点指针,将这k个链表合并,合并后仍然为有序,返回合并后的头节点。
#include <stdio.h>
#include <vector>
#include <algorithm>
struct ListNode {
       int val;
       ListNode* next;
       ListNode(int x) : val(x), next(NULL) {}
};
bool cmp(const ListNode* a, const ListNode* b) {
       return a->val < b->val;
}
// int main() {
//     ListNode a(3);
//     ListNode b(2);
//     ListNode c(5);
//     ListNode d(0);
//     std::vector<ListNode*> node_vec;
//     node_vec.push_back(&a);
//     node_vec.push_back(&b);
//     node_vec.push_back(&c);
//     node_vec.push_back(&d);
//     std::sort(node_vec.begin(), node_vec.end(), cmp);
//     for (int i = 0; i < node_vec.size(); i++) {
//            printf("%d\n", node_vec[i]->val);
//     }
//     return 0;
// }
class Solution {
public:
       //     ListNode* mergeKLists(std::vector<ListNode*>& lists) {//把所有的节点都存储到vector中,排序后,在连接成链表。
       //            std::vector<ListNode*> node_vec;
       //            for(int i = 0; i < lists.size(); i++){
       //                   ListNode *head = lists[i];
       //                   while(head){
       //                           node_vec.push_back(head);
       //                           head = head->next;
       //                   }
       //            }
       //            if(node_vec.size() == 0){
       //                   return NULL;
       //            }
       //            std::sort(node_vec.begin(), node_vec.end(), cmp);
       //            for(int i = 1; i < node_vec.size(); i++){
       //                   node_vec[i-1]->next = node_vec[i];
       //            }
       //            node_vec[node_vec.size()-1]->next = NULL;
       //            return node_vec[0];
       //      }
       ListNode* mergeTwoLists(ListNode* L1, ListNode* L2) {
              ListNode temp_head(0);
              ListNode* ptr = &temp_head;
              while (L1 && L2) {
                      if (L1->val < L2->val) {
                             ptr->next = L1;
                             L1 = L1->next;
                      }
                      else {
                             ptr->next = L2;
                             L2 = L2->next;
                      }
                      ptr = ptr->next;
              }
              if (L1) {
                      ptr->next = L1;
              }
              if (L2) {
                      ptr->next = L2;
              }
              return temp_head.next;
       }
       //分治法
       ListNode* mergeKLists(std::vector<ListNode*>& lists) {//要加& ,调用时,直接将参数的地址传递给mergeKLists
              if (lists.size() == 0) {
                      return NULL;
              }
              if (lists.size() == 1) {
                      return lists[0];
              }
              if (lists.size() == 2) {
                      return mergeTwoLists(lists[0], lists[1]);
              }
              int mid = lists.size() / 2;
              std::vector<ListNode*> sub1_lists;
              std::vector<ListNode*> sub2_lists;
              for (int i = 0; i < mid; i++) {
                      sub1_lists.push_back(lists[i]);
              }
              for (int i = mid; i < lists.size(); i++) {
                      sub2_lists.push_back(lists[i]);
              }
              ListNode* l1 = mergeKLists(sub1_lists);
              ListNode* l2 = mergeKLists(sub2_lists);
              return mergeTwoLists(l1, l2);
       }
};
int main() {
       ListNode a(1);
       ListNode b(4);
       ListNode c(6);
       ListNode d(0);
       ListNode e(5);
       ListNode f(7);
       ListNode g(2);
       ListNode h(3);
       a.next = &b;
       b.next = &c;
       d.next = &e;
       e.next = &f;
       g.next = &h;
       Solution solve;
       std::vector<ListNode*> lists;
       lists.push_back(&a);
       lists.push_back(&d);
       lists.push_back(&g);
       ListNode* head = solve.mergeKLists(lists);
       while (head) {
              printf("%d\n", head->val);
              head = head->next;
       }
       return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值