Leetcode 刷题1

例题一:链表逆序 leetcode206
已知链表头结点指针head,将链表逆序。(不可申请额外空间)
在这里插入图片描述
依次遍历链表节点,每遍历一个节点即逆置一个节点
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

第二题:已知链表头结点指针head,将链表从位置m到n逆序。(不申请额外空间)Leetcode 92
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ListNode *reverseBetween(ListNode* head,int m, int n){
	int chang_len = n-m+1;   //计算需要逆置的节点数
	ListNode *new_head = NULL;  //新节点
	ListNode *pre_head =  NULL;  //逆置的前置节点
	ListNode *result = head;  //最后的节点
	while(head && --m){
		pre_head = head;     //记录head的前置节点
		head=head->next;    
	}
	ListNode *list_tail = head;  //将head指向当前节点 ,即逆置后的节点
	while(head && chang_len){
		ListNode *next = head->next;
		head->next = new_head;
		new_head = head;
		head = next;
		chang_len--;
	}
	list_tail->next = head;  //将尾部相连
	if(pre_head)   //如果头结点存在 说明不是从第一个节点开始的
		pre_head->next = new_head;
	else 
		result = new_head;    //如果pre_head为空,说明m==1从第一个节点开始逆置结果即为逆置后的头结点
	return result;
	
}

第三题:求两个链表的交点
已知链表A的头结点指针headA,链表B的头结点指针headB,两个链表相交,求两链表交点对应的节点。leetcode 160
在这里插入图片描述
1.如果两个链表没有交点,则返回NULL
2.再求交点的过程中,不可以破坏链表的结构或者修改链表的数据域
3.可以确保传入的链表A与链表B没有任何环
4.实现算法尽可能使时间复杂度O(n),空间复杂度O(1)

思路1:使用set求交集
1.遍历链表A,将A中节点对应的指针(地址),插入set
2.遍历链表B,将B中节点对应的指针(地址),在set中查找,发现在set中的第一个节点地址,即是两个链表的交点。

ListNode *getIntersectionNode(ListNode *headA,ListNode *headB){
	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->headB;
	}
	return NULL;
}

思路2:空间复杂度O(1)
步骤1:计算headA链表长度、计算headB链表长度,较长的链表多出的长度
2:将较长链表的指针移动到和较短链表指针对齐的位置
3:headA与headB同时移动,当两指针指向同一个节点时,即找到了

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){
		delta--;
		head=head->next;
	}
	return head;
}

ListNode *getIntersectionNode(ListNode *headA,ListNode *headB){
 int lenA = get_list_length(headA);
 int lenB= get_list_length(headB);
 if(lenA>lenB)
 	forward_long_list(lenA,lenB,headA);
 else 
 	forward_long_list(lenB,lenaA,headB);
while(headA&&headB){
		if(headA==headB)
			return headA;
		headA=headA->next;
		headB=headB->next;
}
return NULL;
}

第三题:链表求环
已知链表中可能存在环,若有环返回环起始节点,否则返回NULL;leetcode 141
在这里插入图片描述
思路1:使用set求环起始节点
1.遍历链表,将链表中节点对应的指针(地址),插入set
2.在遍历时插入节点前,需要在set中查找,第一个在set中发现的节点地址,即是链表环的起点
在这里插入图片描述

ListNode *detectCycle(ListNode *head){
	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;      //没有遇到环,则返回NULL;
}

思路2:快慢指针赛跑
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ListNode *detectCycle(ListNode *head){
	ListNode *fast = head;
	ListNode *slow = head;
	ListNode*meet = NULL;
	while(fast){
		slow = slow->next;
		fast = fast->next;
		while(!fast){
				return NULL;
			}
		fast=fast->next;
		if(fast==slow){
			meet=fast;
			break;
		}
	}
	while(meet&&head){
		if(meet==head)
			return meet;
		meet=meet->next;
		head=head->next;
	}
	return NULL;
}

第四题:链表划分:
已知链表头指针head与数值x,将所有小于x的节点放在大于或等于x的节点前,且保持这些节点的原来的相对位置。Leetcode 86
在这里插入图片描述

思路:使用两个临时节点less_ptr和more_ptr;将节点值大于x的放置在more_ptr后面,小于x的放置在less_ptr后面,最后将less_ptr的尾节点和more_ptr的头结点相连即可。

ListNode *parition(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;
}

第五题:排序链表的合并 leetcode 21
a:已知两个已排序链表头节点指针l1与l2,将这两个链表合并,合并后仍为有序的,返回合并后的头节点。
在这里插入图片描述
思路:比较l1和l2指向的节点,将较小的节点插入到pre指针后,并向前移动较小节点对应的指针
在这里插入图片描述

ListNode *mergeTwoLists(ListNode* l1,ListNode* l2){
	ListNode temp_head(0);
	ListNode *pre = &temp_head;
	while(l1 && l2){
		if(l1->val < l2->val){
				pre->next = l1;
				l1=l1->next;
		}
		else {
			pre->next = l2;
			l2=l2->next;
			}
		pre = pre->next;
	}
	if(l1)
		pre->next = l1;
	if(l2)
	pre->next = l2;
 return temp_head.next;
}

b:已知k个已排序链表头节点指针,将这k个链表合并,合并后仍为有序的,返回合并后的头节点。leetcode 23
在这里插入图片描述
思路:将k*n个节点放到vector中,再将vector排序,再将节点顺序相连。

bool cmp(const ListNode *a,const ListNode *b){
	return a->val < b->val;
}
ListNode *mergeKists(vector<ListNode*>& lists){
	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;
	sort(node_vec.begin(),node_vec.end(),cmp);
	for(int i=0;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 *mergeKists(vector<ListNode*>& lists){
	if(list.size()==0) return NULL;
	if(lits.size()==1) return lists[0];
	if(lists.size()==2) return mergeTwoLists(lists[0],lists[1]);
 
  int mid = lists.size()/2;
  vector<ListNode*> sub1_lists;
    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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值