【JavaScript算法】-链表合辑04

一、06 旋转链表

问题描述

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
在这里插入图片描述

解题思路

1、闭合为环

a、将链表连成环;
b、计算新的Head位置,并将head前一个元素的next值设置为null;
c、返回新的head。

var rotateRight=function(head,k){
	if(head==null||head.next==null) return head;
	let cur=head;
	let count=1;
	while(cur.next){
		cur=cur.next;
		count++;
	}
	cur.next=head;//首尾连接形成环
	k=count-k%count;//计算要移动的距离
	while(k--) cur=cur.next;
	head=cur.next; //head指向第len-k+q个节点,即旋转后的链表的头节点
	cur.next=null;
	return head;
};
2、模拟

a、首先遍历链表求出链表长度len,并找出链表的尾节点tail;
b、因为k的值可能大于链表长度len,所以计算移动距离(翻转后链表的头节点时)需要令k=k%n(长5,移6,实际移1)。再次从头节点head开始遍历,找到第len-k个节点p,那么节点1~p是链表的前len-k个节点,
p+1~len是链表的后k个节点。
c、然后将链表的后k % len个节点和前len - (k % len)个节点连接到一块即可得到翻转后的链表,即令tail.next=head;newhead=p.next;p.next=null;
d、返回新节点newhead.
具体代码如下:

var rotateRight=function(head,k){
	if(head==null||head.next==null){
        return head;
    }
	let len=1;
	let tail=head;
	while(tail.next){ //找到尾节点
		len++;
		tail=tail.next;
	}
	k=len-k%len;
	let p=head;
	while(--k) p=p.next;
	tail.next=head;
	let newhead=p.next;
	p.next=null;
	return newhead;
};

二、83 删除排序链表中的重复元素

问题描述

给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
在这里插入图片描述

解题思路

这个和82题类似,只是82是删除所有重复元素,但是这个题需要保留一个重复的元素。
采用类似的方法虚拟节点+双指针;
a、设置虚拟节点dummyhead,使其next指向head,方便返回结果;
b、设置指针fast=head.next,slow=head。若fast和slow指针的值相同,说明数值重复,此时需要删除fast指针所指向的节点,即slow.next=fast.next,指针fast后移一位;
c、否则,fast和slow指针分别后移一位。

var deleteDuplicates = function(head) {
    if(head==null||head.next==null) return head;
    let dummyhead=new ListNode(0,head);
    let fast=head.next;
    let slow=head;
    while(fast){
        if(fast.val==slow.val){
            slow.next=fast.next;
        }else{
            slow=fast;
        }
         fast=fast.next;
    }
    return dummyhead.next;
};

三、 86 分隔链表

问题描述

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
在这里插入图片描述

解题思路

1、使用栈

a、设置虚拟节点dummyhead,作为新建链表的头节点,方便返回分隔后的链表;
b、令p=dummyhead来形成新链表,令指针cur=head来遍历原链表,cur.val和x做比较,小于x的节点采用尾插法直接接在新建链表p的末尾,大于x的先存入新建栈bigger中;
c、遍历结束后,令p.next=null,这是为了断开链表,防止后面存在大于x的节点未被去除;
d、采用头插法,将栈中元素弹出接在链表尾部;
e、返回dummyhead.next。
具体代码如下

var partition=function(head,x){
	if(head==null||head.next==null) return head;
	let bigger=[];
	let dummyhead=new ListNode(0);
	let p=dummyhead;
	let cur=head;
	while(cur){
		if(cur.val<x){
			p.next=cur;
		}else{
			bigger.push(cur.val);	
		}
		cur=cur.next;
	}
	p.next=null;
	while(bigger.length){
		let newnode=new ListNode(bigger.pop());
		newnode.next=p.next;
		p.next=newnode;
	}
	return dummyhead;
};
2、虚拟节+双指针

a、初始化虚拟节点dmy和快慢指针fast、slow;
b、令慢指针slow水中保持指向新形成链表的最后一个小于x的节点;
c、fast从slow开始向后寻找其他小于x的节点;
i、若找到小于x的节点,则需要将该节点摘出来拼接到slow的后面,并将slow后移,始终保持slow指向新建立节点中最后一个小于x的节点;
ii、若未找到则fast指针向后迭代
d、返回dmy.next;

var partition=function(head,x){
	let dmy=new ListNode(-1,head);
	let slow=dmy;
	let fast=null;
	while(slow!=null&&slow.next!=null){
		if(slow.next.val>=x) break;
		slow=slow.next;
	}
	fast=slow;
	while(fast!==null&&fast.next!==null){
		if(fast.next.val<x){
			let tmp=fast.next;
			fast.next=fast.next.next;
			tmp.next=slow.next;
			slow.next=tmp;
			slow=slow.next;
		}else{
			fast=fast.next;
		}
	}
	return dmy.next;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值