2022-4-24周末总结
方法:模拟
思路
出现1的时候就记录1的索引,然后和之前出现1的索引位置进行比较,遍历完的最大值就是要找的值。
代码实现
/**
* @param {number} n
* @return {number}
*/
const binaryGap = function(n) {
let temp = n.toString(2)
let res = 0
for (let i = 0,preIndex=0; i < temp.length; i++) {
if (temp[i]==='1'){
res = Math.max(res,i-preIndex)
preIndex = i
}
}
return res
};
console.log(binaryGap(22))
2022-4-18
题目:字典排序数解题思路
方法:dfs深度优先搜索
字典序样例
比如n=123 那么输出结果为
1,10,100,101109,11,110119,12,120123,13,1419,2,20,21.
整体思路
对于一个整数num,字典排序树的情况对应下边几种情况
- 先将num*10(在num后边附加一个0),并判断num是否超过了数字n,如果没有则说明符合字典排序树的要求
- 假如num mod 10===9 或者num+1>n 则说明末尾的数字已经搜索完了,则返回上一位,也就是对num/10向下取整,然后num++ 一直判断直到循环结束。
如果一个数需要取中间的值可以 num >> 1右移一位 向下取整
代码实现
const lexicalOrder = (n) => {
let res = []
// 最小的字典数,先放入数组
let num = 1
// 控制放入n个数字
for (var i = 0; i < n; i++) {
res.push(num)
// num后边加0还符合要求就直接放入
if (num * 10 <= n) {
num *= 10
} else {
// 不符合要求就先判断是否,到了对后一个字典数
// 如果没到就num++ 然后push进答案数组中,假如到了最后,就回退到上一个数字. 比如n=120 此时num=109 则需要让num变成11、或者n=123此时num=123 则需要让num=13
while (num % 10 === 9 || num + 1 > n) {
num = Math.floor(num/10)
}
num++
}
}
return res
}
2022-4-19
题目:两数相加
方法:直接相加
整体思路
遍历两个链表,直接在对应的数值相加,假如某个链表为空,可以用0代替它的数值相加。根据题意
可以知道相加的规则为:
- 相加没有进位 ,这种情况可以直接将值放入新链表当中
- 当相加有进位的情况,sum的值mod10 作为链表的新数值加入到链表。并置进位变量carry = Math.floor(sum/10),继续迭代
需要注意当链表结束遍历的时候进位的数值为1则需要在链表的结尾加入值为1的节点
代码实现
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
const addTwoNumbers = function(l1, l2) {
/**
* 当时以为js不能新建链表然后再新链表上操作,因为报出了内存溢出的错误,后来发现是后边的判断条件出现了错误
* @type {ListNode}
*/
// 创建新链表用于存放结果
let newNode = new ListNode()
let temp = newNode
let carry = 0
while (l1!==null||l2!==null) {
let x = l1 === null ? 0:l1.val
let y = l2 === null ? 0:l2.val
let sum = x + y + carry
/**
* 注意点: sum/10 再js中不会自动向下取整 所以需要Math函数
* @type {number}
*/
carry = Math.floor(sum/10)
sum = sum%10
temp.next = new ListNode(sum)
temp = temp.next
/**
* 这个判断条件为链表不为空
*/
if (l1) {
l1 = l1.next
}
if (l2) {
l2 = l2.next
}
if (carry===1) {
temp.next = new ListNode(carry)
}
}
return newNode.next
};
2022-4-20
题目:文件最长绝对路径
方法:栈
整体思路
大致方法:用栈来维护结果字符串的长度,按照层级遍历。
- 首先将字符串通过\n进行分割,返回分割后的数组再处理
- 遍历数组,数组中的某个元素代表文件目录的某个层级,下边需要处理的是每个层级的绝对路径长度
- 当文件在某个层级的时候,其现在的最长文件绝对路径包括现在层级字符串的长度加上前面所有层级字符串的长度,而字符串的长度需要用栈来维护
- 较难处理的是层级的变换,当dir的一个子目录遍历完之后,比如此时在subsubdir1,现在的层级为3,但是subdir1已经遍历结束,下一个文件为subdir2就需要回退到第一级目录,需要改变栈维护的字符串长度。
String.prototype.split方法
// 传入一个要分割的字符返回分割后的数组
String.prototype.split()
代码实现
/**
* @param {string} input
* @return {number}
*/
const lengthLongestPath = function (input) {
let res = 0
let stack = []
stack.push(0)
let newString = input.split('\n')
for (let i = 0; i < newString.length; i++) {
// 确定当前文件的层级,当没有/t的时候返回-1,说明文件在0级。
// 需要注意的是lastIndexOf
let level = newString[i].lastIndexOf('\t') + 1
/**
* 较难理解的部分
*/
while (stack.length - level > 1) {
stack.pop()
}
// \t\tsubsubdir1 这个字符串的长度为出去\之后的长度,计算length的时候需要减去层数补上1 也就是说长度为subsubdir1/ 这个/是算在字符串长度中的
// 后边的加1表示/这个符号
let length = stack[stack.length - 1] + (newString[i].length - level + 1)
console.log(newString[i])
stack.push(length)
if (newString[i].includes('.')) {
// 这个-1是为了把/这个符号的长度给去掉,因为是最后一个文件所以没/
res = Math.max(res, length - 1)
}
}
return res
};
题目:无重复的最长回文子串长度
方法1:滑动窗口+队列
方法2:队列
整体思路
解法1:用数组模拟队列,并遍历字符串s,假如当前遍历的字符串在前边没有出现过则就queue.push()进栈,假如出现过就需要删除队列前边的元素, 不断迭代,计算最大值。
解法2:采用滑动窗口的方式
- 创建窗口,这个题目可以用Set集合
- 当所求的字符串满足题目要求的时候左指针不动,右指针后移,并满足要求的字符串add进set集合, 通知右指针后移。
- 当继续遍历遇到与前边重复的字符串,则需要删除前边元素,继续循环。
代码实现
/**
* @param {string} s
* @return {number}
* 解法1:采用队列的方法动态删除
*/
const