算法与数据结构-链表LeetCode

链表操作

1,链表逆序-a leetcode 206

整个链表进行逆序

#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
			head->next=new_head;//更新head->next
			new_head=head;		//移动new_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=slove.reverseList(&a);
	printf("After reverse:\n");
	while(head){
		printf("%d\n",head->val);
		head=head->next;
	}
	return 0;
}

2,链表逆序-b leetcode 92

已知头节点指针head,将链表从位置m到n逆序.(不申请额外空间)

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_tail=head;//将modify_list_tail指向当前的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_tail->next=head;
		if(pre_head){ //如果pre_head不为空说明不是第一个节点开始逆置的m>1
			pre_head->next=new_head;//将逆置的链表的开始的节点前驱与逆置后的头节点连接
		}
		else{
			result=new_head; //如果pre_head为空,说明m==1.从第一个节点开始逆置,结果即为逆置后的头节点
		}
		return result;
	}
};	

3,两个链表的交点 leetcode 160

#include <stdio.h>

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

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;
    }
};

4,两个链表是否有环 leetcode 141 142

快慢指针的思想,(环形赛道) 环的起始位置.

#include <stdio.h>

struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(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 (head == meet){
	    		return head;
	    	}
	    	head = head->next;
	    	meet = meet->next;
	    }
        return NULL;
    }
};

5, 链表划分 leetcode 86

在这里插入图片描述

#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);//创建临时节点 小于x
    	ListNode more_head(0);//创建临时节点 大于x
    	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;//将more节点置空,即链表尾节点指向的指针置空
        return less_head.next;//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;
}

6, 复杂链表的深度拷贝 leetcode 138

复杂链表的深度拷贝
在这里插入图片描述

#include <stdio.h>
#include <map>
#include <vector>	
	
struct RandomListNode {
	int label;
	RandomListNode *next, *random;
	RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
};

class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
    	std::map<RandomListNode *, int> node_map;//地址与节点 映射关系记录map
    	std::vector<RandomListNode *> node_vec;//使用vector根据存储节点位置访问地址
    	RandomListNode *ptr = head;
    	int i = 0;
    	while (ptr){
	    	node_vec.push_back(new RandomListNode(ptr->label));
	    	node_map[ptr] = i;
	    	ptr = ptr->next;
	    	i++;
	    }
	    node_vec.push_back(0);
	    ptr = head;
	    i = 0;
	    while(ptr){//再次遍历,连接新链表next,与random指针
    		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(){
	RandomListNode a(1);
	RandomListNode b(2);
	RandomListNode c(3);
	RandomListNode d(4);
	RandomListNode e(5);
	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;
	RandomListNode *head = solve.copyRandomList(&a);	
	while(head){
		printf("label = %d ", head->label);
		if (head->random){
			printf("rand = %d\n", head->random->label);
		}
		else{
			printf("rand = NULL\n");
		}
		head = head->next;
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值