「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」 剑指 Offer II 024. 反转链表
思路1:递归法
var reverseList = function(head) {
if(head === null || head.next === null) return head;
let left = head.next;
const t = reverseList(head.next);
head.next = left.next;
left.next = head;
return t
};
思路2:迭代法
这个思路很好理解,使用3个指针;头指针pre,当前指针curr,下一节点指针next;
将当前指针curr.next 指向pre;
将头指针指向当前指针;
将当前指针使命完成,让当前指针指向下一指针;
下一指针使命完成,下一节点指针next应该指向下下一节点;判断一下节点next是否为null,null是没有下下一节点的
var reverseList = function(head) {
if(head === null) return head;
let pre = null;
let curr = head;
let next = head.next;
while(curr){
curr.next = pre;
pre = curr;
curr = next;
next = next === null?null:next.next
}
return pre
};
703. 数据流中的第 K 大元素
思路1
根据最大K元素很容易想到排序;将add的数据添加到数组,在添加过程中,通过查找方法将val数值放到数组对应位置,使添加完数据的数组依然是有序的;输出第K个元素即可得到答案;
代码如下:
var KthLargest = function(k, nums) {
nums.sort((a,b)=>b-a)
this.list = nums
this.idx = k
};
KthLargest.prototype.add = function(val) {
const idx = this.idx;
const len = this.list.length;
for(let i = 0 ; i < len ; i++){
if(this.list[i] <= val){
this.list.splice(i,0,val);
break;
}
}
if(this.list.length === len){
this.list.push(val)
}
return this.list[idx-1]
};
思路2
通过一上代码,你已经AC本题;但是进一步思考;既然只需要知道第K个最大值;哪在上述代码中是不是可以优化一下?
既然只需要获取第K个最大值,哪我排序的数组长度是不是只需要K;
通过一上代码,进一步优化代码如下:
var KthLargest = function(k, nums) {
nums.sort((a,b)=>b-a);
// 仅仅截取前K个数字
this.list = nums.slice(0,k+1)
this.idx = k
};
KthLargest.prototype.add = function(val) {
const idx = this.idx;
const len = this.list.length;
for(let i = 0 ; i < len ; i++){
if(this.list[i] <= val){
this.list.splice(i,0,val);
break;
}
}
if(this.list.length === len){
this.list.push(val)
}
//超出K个元素,删除数组中最后一个
if(this.list.length === idx){
this.list = this.list.slice(0,idx)
}
return this.list[idx-1]
};
面试题 02.07. 链表相交
思路:?不能说毫无思路,只能说没有头绪,手动🤪。
首先我是这么考虑的;
遍历一遍链表A,在A中添加标识数据,比如A.index = "A";
再遍历链表B,在B中找到index;第一个index有值的节点就是相交节点;
这思路绝对能找出相交节点;
奈何题目着重要求保持其原始结构 凉凉~!
在想!!!
思路2
假设:
链表A=[3,4,5,6];
链表B=[5,6];
通过【尾部对齐】法将链表A、B变化为:
A = [5,6];
B = [5,6];
这不就可以了?
按照这个思路,获取A、B链表长度,将链表长度较长的链表通过while将链表与较短链表长度一致;然后再对比两链表节点;如果节点相同,则两链表相交,否则链表不相交;
根据上述思路书写代码如下,但是这段代码明显有可优化的空间;
时间复杂度分析O(max(A.length,B.length))
var getIntersectionNode = function(headA, headB) {
let l1 = 0;
let headerA = headA;
let headerB = headB;
while(headerA){
l1++;
headerA = headerA.next;
}
let l2 = 0;
while(headerB){
l2++;
headerB = headerB.next;
}
// 如果两链表长度相同
if(l1 === l2){
headerA = headA;
headerB = headB;
while(headerA && headerB){
if(headerA === headerB) return headerB;
headerA = headerA.next;
headerB = headerB.next;
}
return null
}else if(l1 < l2){
headerA = headA;
headerB = headB;
while(l1 < l2){
headerB = headerB.next
l2--;
}
while(headerA && headerB){
if(headerA === headerB) return headerB;
headerA = headerA.next;
headerB = headerB.next;
}
return null
}else{
headerA = headA;
headerB = headB;
while(l2 < l1){
headerA = headerA.next
l1--;
}
while(headerA && headerB){
if(headerA === headerB) return headerB;
headerA = headerA.next;
headerB = headerB.next;
}
return null
}
};
思路2:
脑子实在想不出来,找了支笔写写画画,画出来个这;
得出来个核心:a+b = b+a;😄;
先假设如果两个链表相交,且相交点为c;
那么就可以设:
链表A表头到交点长度为a,交点c到链表A位长度为c;
链表B表头到交点长度为b,交点c到链表B位长度为c;
那么链表A、链表B同时向前走一定有:
链表A向前长度a到交点c,在向前走长度c到达链表A尾,在向前走长度b又回到了交点c;
同样,链表B向前长度b到交点c,在向前走长度c到达链表B尾,在向前走长度a回到交点c;
结论:a + c + b = b + c + a;
根据这个思路:写代码如下:
var getIntersectionNode = function(headA, headB) {
let node1 = headA;
let node2 = headB;
while(node1 !== node2){
//如果二者不相同,两链表同时向前步进;
node1 = node1 === null?headB:node1.next;
node2 = node2 === null?headA:node2.next
}
//如果相同,返回链表
return node1
};
看看这代码量,看看这思路;羡慕不羡慕
61. 旋转链表
这题对目前我的水品还是有点吃力的;还好,我知道如何旋转JavaScript数组的旋转,我准备参照这个思路,实现这个链表反转;
var rotateRight = function(head, k) {
let len = 0;
let header = head;
//获取链表长度,因为旋转移动的K值可能超过链表长度
while(header){
len++;
header = header.next
}
//超过链表长度 取余数即可
let l = k%len;
// 余数为0 表示链表与旋转长度一致;返回原链表
if (!head || l == 0) return head;
//假设链表长度为l;将链表按照k分为左侧部分与右侧部分,左侧部分长度为l-k;右侧部分长度为k;
// 将左右部分互换即可实现链表旋转
//通过快慢指针得到左右部分;
//
let fase = head;
while(l){
fase = fase.next;
l--;
}
let slow = head;
let last = 0;
while(fase && slow){
fase = fase.next;
slow = slow.next;
last++;
}
let resule = slow;
while(resule && resule.next){
resule = resule.next
}
// 将左侧链表放在右侧链表中
while(last){
resule.next = new ListNode(head.val);
head = head.next;
resule = resule.next;
last--;
}
//返回左侧链表表头
return slow
};
反转二叉树
这题第一个就想到递归
var invertTree = function(root) {
if(root === null) return null;
let left = root.left
root.left = invertTree(root.right);
root.right = invertTree(left);
return root
};