背景
今天开始计划刷《剑指offer》的题目,在牛客网刷的,总共81道题目,今天过后还剩75道,预计每天刷4题,如果题目难的话,可能会减少。这样的话大概20天刷完。但肯定没那么顺利,再加buffer 5天,预计25天刷完。除去周六日,大概需要到11.14号刷完。小伙伴有没有一起刷的,可以组队刷题啊。
最开始是链表的题目,今天刷的,因为大部分之前做过,所以做起来还比较快。今天刷了4道链表题目和3道其他题目,最后一道题没做出来,通过chatgpt做出来了,泪奔啊,chatgpt真niubi。
我先记录没刷出来的题。
题目
题目一 2的幂次方表示
任何一个整数都可以用2的幂次方表示,例如:
- 137 = 2的7次方+2的3次方+2的0次方
- 同时约定方次用括号来表示,即a的b次方可表示为a(b)。由此可知,137可表示为:
- 2(7) + 2(3) + 2(0)
- 进一步:7 = 2的2次方,2的1次方(2的1次方用2表示),2的0次方
- 3=2的1次方+2的0次方
- 索引最后137可表示为
- 2(2(2)+2+2(0)) + 2(2 + 2(0)) + 2(0)
题目输入:
- 输入n (n <= 20000)
- 输出字符串表示
这个题目比较绕,题目看了一会才明白。
思路
这题我没做出来,哭死,然后求助了chatgpt😭
- n 不断除以2,如果结果是奇数,则进行拼接,因为从题目描述,最后的幂也需要再次表示出来,所以这题目应该需要递归来实现。
- 递归要确定终止条件:如果最后结果是0,则返回
2(0),如果是1,则返回2 - n不断除以2的过程中,如果2的幂集统计超过了2,则递归进行处理。
function binaryInt(num) {
if (num === 0) {
return "0";
} else if (num === 1) {
return "2(0)";
}
let val = num;
let count = 0;
let str = '';
while (val > 0) {
// 如果当前是奇数,则需要进行处理
if (val % 2) {
if (str) {
str = '+' + str;
}
if (count === 0) {
str = '2(0)' + str;
} else if (count === 1) {
str = '2' + str;
} else {
// 如果当前的幂指数大于2,则递归进行处理
str = '2(' + binaryInt(count) + ')' + str;
}
}
val = val >> 1;
count++;
}
console.log(str);
return str;
}
binaryInt(137);
剑指offer题目
题目二 25.合并两个有序链表.js
这个题目比较简单,因为创建的新的链表来写的,所以每次比较两个节点,将小的值构造节点插入新的链表,并且小的链表后移,直到有某一个链表为空。最后将剩余的拼接上即可。
/*
* function ListNode(x){
* this.val = x;
* this.next = null;
* }
*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param pHead1 ListNode类
* @param pHead2 ListNode类
* @return ListNode类
*/
function Merge( pHead1 , pHead2 ) {
let node1 = pHead1;
let node2 = pHead2;
let newHead = new ListNode();
let node = newHead;
while (node1 && node2) {
let newNode1 = new ListNode();
if (node1.val < node2.val) {
newNode1.val = node1.val;
node1 = node1.next;
} else {
newNode1.val = node2.val;
node2 = node2.next;
}
node.next = newNode1;
node = newNode1;
}
if (node1) {
node.next = node1;
}
if (node2) {
node.next = node2;
}
return newHead.next;
}
题目三 52.两个链表的第一个公共节点.js
- 统计两个链表的长度
- 判断是哪个长,将长链表先走diff步,然后一起后移,直到node节点相同就找到了公共的节点。
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function FindFirstCommonNode(pHead1, pHead2)
{
let len1 = 0;
let len2 = 0;
let node1 = pHead1;
let node2 = pHead2;
while (node1) {
node1 = node1.next;
len1++;
}
while (node2) {
node2 = node2.next;
len2++;
}
node1 = pHead1;
node2 = pHead2;
if (len1 > len2) {
let diff = len1 - len2;
while (diff--) {
node1 = node1.next;
}
} else {
let diff = len2 - len1;
while (diff--) {
node2 = node2.next;
}
}
while (node1 && node2 && node1.val !== node2.val) {
node1 = node1.next;
node2 = node2.next;
}
return node1;
}
题目四 23.链表中环的入口结点.js
这个题目很经典,快慢指针的经典解法,这个题目的低点难度的题目是判断两个链表是否相交,如果快慢指针有相遇了则说明相交。但这个题是求环的入口,所以不光要求出相交节点,求出相交节点后,再从头部和相交节点出来,直到遇到相同节点就找到了点,为啥是这么做?这个要通过数学推导而来。具体的可以看环形链表这个的题解,还是挺详细的。
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function EntryNodeOfLoop(pHead)
{
let fast = pHead;
let slow = pHead;
while (fast && slow && fast.next) {
fast = fast.next.next;
slow = slow.next;
if (fast === slow) {
break;
}
}
let node = pHead;
while (node && slow && node.next) {
if (node === slow) {
return node;
}
node = node.next;
slow = slow.next;
}
return null;
}
题目五 22.链表中倒数最后k个结点.js
这个题还比较简单,先走k步,然后再来一个指针一起走,但是这个要注意的是k如果大于pHead的长度,则需要返回null。
function FindKthToTail( pHead , k ) {
let node = pHead;
while (k-- && node) {
node = node.next;
}
// 如果k的长度大于length长度,则返回null
if (k >= 0) {
return null;
}
let node1 = pHead;
while (node) {
node = node.next;
node1 = node1.next;
}
return node1;
}