/**
* @param {string[][]} items
* @param {string} ruleKey
* @param {string} ruleValue
* @return {number}
*/
var countMatches = function(items, ruleKey, ruleValue) {
let resSum=0
const ruleValueArr=["type","color","name"]
const index=ruleValueArr.indexOf(ruleKey)
if(index<0)
return 0
for(let item of items){
if(item[index]==ruleValue)
resSum++
}
return resSum
};
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
for(let i=0,len=nums.length;i=0&&nums.indexOf(findingNum)!==i){
return [i,nums.indexOf(findingNum)].sort((a,b)=>a-b)
}
}
return []
};
当时第一反应想到的解法
/**
* 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}
*/
var addTwoNumbers = function(l1, l2) {
function reverseList(head) {
let cur = head
let pre = null
let res = ""
while (cur != null) {
const next = cur.next
cur.next = pre
pre = cur
cur = next
}
while (pre != null) {
res = res + pre.val
pre = pre.next
}
return res
}
let res1 = reverseList(l1)
let res2 = reverseList(l2)
let res3 = (Number(res1) + Number(res2)).toString().split("").reverse()
let resL = new ListNode()
let cur = resL
for (let i = 0; i < res3.length; i++) {
cur.next = new ListNode(res3[i])
cur = cur.next
}
return resL.next
};
就是翻转链表获取参数然后数字相加,但是发现了最后两题过不去,数字范围太大超过最大值导致返回NaN了。
后来想到 应该可以直接链表相加。满10进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}
*/
var addTwoNumbers = function(l1, l2) {
//当前指针
let cur1 = l1
let cur2 = l2
let carry = 0
let res = new ListNode()
let resCur = res
while (cur1 && cur2) {
let tempRes = cur1.val + cur2.val + carry
resCur.next = new ListNode(tempRes % 10)
carry = Math.floor(tempRes / 10)
cur1 = cur1.next
cur2 = cur2.next
resCur = resCur.next
}
while (cur1) {
let tempRes = cur1.val + carry
resCur.next = new ListNode(tempRes % 10)
carry = Math.floor(tempRes / 10)
cur1 = cur1.next
resCur = resCur.next
}
while (cur2) {
let tempRes = cur2.val + carry
resCur.next = new ListNode(tempRes % 10)
carry = Math.floor(tempRes / 10)
cur2 = cur2.next
resCur = resCur.next
}
if (carry > 0) {
resCur.next = new ListNode(carry)
}
return res.next;
};
第一反应解法
时间复杂度太高了,她测试用例居然输入了那么长的字符串
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
//双指针法
let p1 = 0
let res = ""
while (p1 < s.length) {
let p2 = p1
while (p2 < s.length) {
let target = s.slice(p1, p2 + 1)
if (target === target.split("").reverse().join("")) {
res = res.length > target.length ? res : target
}
p2++
}
p1++
}
return res
};
第二反应采用的是中心扩散的方法 就是以一个字符为中心左右移动开始指针和结束指针,判断是否回文。
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function (s) {
//中心扩散 中心指针
//回文的几种基本情况
/**
* @type 仅自身回文 “a”
* @type 偶数回文 “abba”
* @type 中心对称奇数回文 “aba”
*/
let res = ""
for (let len = s.length, i = 0; i < len; i++) {
getResString(i, i) //情况1 3 以某元素为中心左右扩展
getResString(i, i + 1)//情况2 以i和i+1元素为起始左右扩展
}
function getResString(left, right) {
while (left >= 0 && right < s.length) {
if (s.charAt(left) !== s.charAt(right)) {
return
} else {
let target = s.slice(left, right + 1)
res = res.length > target.length ? res : target
left--
right++
}
}
}
return res
};
第一眼看完只能说是没什么思路。思考了一会:直接看答案
/**
* @type .表示任意字符 *表示前面的单个字符任意数目重复
* @param {string} s 字符串
* @param {string} p 字符规律
* @return {boolean}
*/
var isMatch = function (s, p) {
//从左向右扫描的话 *的出现会影响结果 改为从右向左扫 把b*看成一个整体进行子集匹配
if (s == null || p == null) return false;
const sLen = s.length, pLen = p.length;
const dp = new Array(sLen + 1);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(pLen + 1).fill(false); // 将项默认为false
}
// base case
dp[0][0] = true;
for (let j = 1; j < pLen + 1; j++) {
if (p[j - 1] == "*") dp[0][j] = dp[0][j - 2];
}
// 迭代
for (let i = 1; i < sLen + 1; i++) {
for (let j = 1; j < pLen + 1; j++) {
if (s[i - 1] == p[j - 1] || p[j - 1] == ".") {
dp[i][j] = dp[i - 1][j - 1];
} else if (p[j - 1] == "*") {
if (s[i - 1] == p[j - 2] || p[j - 2] == ".") {
dp[i][j] = dp[i][j - 2] || dp[i - 1][j - 2] || dp[i - 1][j];
} else {
dp[i][j] = dp[i][j - 2];
}
}
}
}
return dp[sLen][pLen]; // 长sLen的s串 是否匹配 长pLen的p串
}
暴力解法 计算出所有的组合比较大小 肯定超时就不试了,只能想其他的方法:
思路就是 左右指针 左指针如果移动到比上一位小的height 则跳过判断,右指针左移同理。
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function (height) {
//双指针法
let maxS = 0
let i = 0, tempStartMaxHeight = 0
while (i < height.length - 1) {
if (height[i] > tempStartMaxHeight) {
let j = height.length - 1, tempEndMaxHeight = 0
while (j > i) {
if (height[j] > tempEndMaxHeight) {
let tempS = Math.min(height[i], height[j]) * (j - i)
maxS = tempS > maxS ? tempS : maxS
tempEndMaxHeight = height[j]
}
j--
}
tempStartMaxHeight = height[i]
}
i++
}
return maxS
};
猛一看全是思路,细想不暴力解决的话还是有点东西:
自己瞎写的通过了 但是算不上简洁
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
let res = []
let left = nums.filter(item => {
return item < 0
})
let right = nums.filter(item => {
return item >= 0
})
for (let i = 0; i < left.length; i++) {
for (let j = 0; j < right.length; j++) {
let target = 0 - left[i] - right[j]
if (left.indexOf(target, i + 1) !== -1 || right.indexOf(target, j + 1) !== -1) {
let tempArrStr = [left[i], right[j], target].sort((a, b) => a - b).join("!")
if (!res.includes(tempArrStr))
res.push(tempArrStr)
}
}
}
res = res.map(item => {
return item.split("!")
})
let zeroNum = 0
for (let item of right) {
if (item === 0) {
zeroNum++
}
}
if (zeroNum >= 3) {
res.push([0, 0, 0])
}
return res
};
看着一般
回溯法:JS算法之回溯法_js回溯算法_前端小魔女的博客-CSDN博客
/**
* @param {string} digits
* @return {string[]}
*/
var letterCombinations = function (digits) {
let res = []
if(digits.length===0) return []
const digitsObj = {
"1": [],
"2": ["a", "b", "c"],
"3": ["d", "e", "f"],
"4": ["g", "h", "i"],
"5": ["j", "k", "l"],
"6": ["m", "n", "o"],
"7": ["p", "q", "r", "s"],
"8": ["t", "u", "v"],
"9": ["w", "x", "y", "z"]
}
/**
*
* @param {number} index 当前处理的digits索引
* @param {string} path 当前生成的组合
*/
function dfs(index, path) {
if (index === digits.length) res.push(path)
else if (index < digits.length) {
for (let item of digitsObj[digits.charAt(index)]) {
path = path + item
dfs(index + 1, path)
path = path.slice(0, path.length - 1)
}
}
}
dfs(0, [])
return res
};
指针法怼它就完事了
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
let res = new ListNode()
res.next = head
let o = res
let p = head
let q = head
for (let i = 0; i < n-1; i++) {
q = q.next
}
while (q.next) {
o = o.next
p = p.next
q = q.next
}
o.next = p.next
return res.next
};
经典题目 入栈出栈思维就好
/**
* @param {string} s
* @return {boolean}
*/
var isValid = function (s) {
let left = ["(", "[", "{"]
let tempItems = []
for (let i = 0; i < s.length; i++) {
if (left.includes(s.charAt(i))) {
tempItems.push(s.charAt(i))
} else if (s.charAt(i) === ")" && tempItems[tempItems.length - 1] === "(") {
tempItems.pop()
} else if (s.charAt(i) === "]" && tempItems[tempItems.length - 1] === "[") {
tempItems.pop()
} else if (s.charAt(i) === "}" && tempItems[tempItems.length - 1] === "{") {
tempItems.pop()
} else {
return false
}
}
if (tempItems.length === 0) return true
return false
};
经典中的经典了
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} list1
* @param {ListNode} list2
* @return {ListNode}
*/
var mergeTwoLists = function(list1, list2) {
let res=new ListNode()
let o=res
while(list1&&list2){
if(list1.val
还是回溯法 只不过可以剪枝
let res = []
let path = ""
function getLength(str, target) {
return str.split(target).length - 1
}
function dfs(index) {
if (index === 2 * n) {
res.push(path)
} else {
for (let item of ["(", ")"]) {
if (item === "(" && getLength(path, "(") < n) {
path = path + "("
dfs(index + 1)
path = path.slice(0, path.length - 1)
} else if (item === ")" && getLength(path, "(") > getLength(path, ")")) {
path = path + ")"
dfs(index + 1)
path = path.slice(0, path.length - 1)
}
}
}
}
dfs(0)
return res
虽然是困难题,但是我的解决办法就是循环执行11题,两两排序。就比较简单了。
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode[]} lists
* @return {ListNode}
*/
var mergeKLists = function (lists) {
if (lists.length === 0) return null
let res = lists[0]
function sortTwoList(l1, l2) {
let o = new ListNode()
let res = o
while (l1 && l2) {
if (l1.val < l2.val) {
o.next = l1
l1 = l1.next
} else {
o.next = l2
l2 = l2.next
}
o = o.next
}
while (l1) {
o.next = l1
o = o.next
l1 = l1.next
}
while (l2) {
o.next = l2
o = o.next
l2 = l2.next
}
return res.next
}
for (let i = 1; i < lists.length; i++) {
res = sortTwoList(res, lists[i])
}
return res
};
做的时候没啥思路太困了 看了官方的方法
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var nextPermutation = function(nums) {
//逆序找变小值返回索引
let indexMin = -1
let changeIndex = -1
for (let i = nums.length - 2; i >= 0; i--) {
if (nums[i] < nums[i + 1]) {
indexMin = i
break
}
}
if (indexMin === -1) return nums.sort((a, b) => a - b)
//查找第一个比min大的数
for (let i = nums.length; i >= indexMin; i--) {
if (nums[i] > nums[indexMin]) {
changeIndex = i
break
}
}
//交换两个数的位置
let tempData = nums[indexMin]
nums[indexMin] = nums[changeIndex]
nums[changeIndex] = tempData
//将后面的排序
let tempArray = []
for (let i = nums.length - 1; i > indexMin; i--) {
tempArray.push(nums.pop())
}
nums.push(...tempArray)
};
开始懒得想直接暴力求解 果然超时
/**
* @param {string} s
* @return {number}
*/
var longestValidParentheses = function(s) {
let maxLength = 0
function judge(str) {
let list = []
for (let i = 0; i < str.length; i++) {
let target = str.charAt(i)
if (target === "(") {
list.push("(")
} else if (target === ")" && list[list.length - 1] === "(") {
list.pop()
} else {
return false
}
}
if (list.length === 0) return true
return false
}
for (let pre = 0; pre < s.length; pre++) {
for (let next = 1; next < s.length; next++) {
if(s.length-pre target.length ? maxLength : target.length
}
}
}
return maxLength
};
后来直接去看答案 还是答案想的周到,这里采用双指针法
/**
* @param {string} s
* @return {number}
*/
var longestValidParentheses = function (s) {
let left = 0
let right = 0
let maxLength = 0
for (let i = 0; i < s.length; i++) {
const target = s.charAt(i)
if (target === "(") {
left++
} else if (target === ")") {
right++
}
if (right > left) {
right = 0
left = 0
}else if (left === right) {
const length = 2 * right
maxLength = maxLength > length ? maxLength : length
}
}
right=left=0
for (let i = s.length - 1; i >= 0; i--) {
const target = s.charAt(i)
if (target === "(") {
left++
} else if (target === ")") {
right++
}
if (right < left) {
right = 0
left = 0
}else if (left === right) {
const length = 2 * left
maxLength = maxLength > length ? maxLength : length
}
}
return maxLength
};
关于贪心算法的补充
贪心算法详解
后面有几道过于简单的就省略掉了。