二分法查找
二分法查找
function search(nums, target) {
let left = 0
let right = nums.length - 1
while(left <= right) {
let mid = left + (right -left)/2
if(nums[mid] < target) {
left = mid + 1
} else {
right = mid - 1
}
return left
}
}
双指针
平方数排序
function sortSqurt(nums) {
let left = 0, right = nums.length-1
let res = []
while(left<= right) {
let l = nums[left] * nums[left]
let r = nums[right] * nums[right]
if(l< r) {
res.unshift(r)
r--
} else {
res.unshift(l)
l++
}
}
return res
}
sortSqurt([-9,-1,0,3,6])
数组轮转
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释: 向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
// 利用数组的倒置
funtion rotate(nums, k) {
let reserve = function(start, end) {
while(start< end) {
let temp = nums[start]
nums[start] = nums[end]
nums[end] = temp
start++
end--
}
}
k %= nums.length;
reserve(0, nums.length-1)
reverve(0,k-1)
reverer(k, nums.length-1)
return nums
}
移动零
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
// 快慢指针
// 快指针遇到非零数值后,慢指针跟进赋值
// 当快指针指到尾部时,满指针收集了所有的非零数,之后慢指针补齐0
function solution(nums) {
let fast = 0
let slow = 0
while( fast < nums.length ) {
if(nums[fast] !=0) {
nums[slow++] = nums[fast]
}
fast ++
}
while ( slow < nums.length ) {
nums[slow++] = 0
}
return nums
}
javascipt
function move0(nums) {
let temp = []
for(let i = 0; i< nums.length; i++) {
if(nums[i] != 0) {
temp.push(i)
}
}
for(let j= nums.length - temp.length; j< nums.length; j++) {
nums[j] = 0
}
return nums
}
两数之和
//双循环查找
// function twoSum(nums, target) {
// for(let fast = 0; fast< nums.length; fast++) {
// let temp = nums[fast]
// for(let slow = fast + 1; slow < nums.length; slow ++) {
// console.log(slow, fast)
// if(nums[slow] == target - temp) {
// return [fast+1, slow+1]
// }
// }
// }
// }
var twoSum = function(numbers, target) {
let left = 0
let right = numbers.length -1
while(left <= right) {
let temp = numbers[left] + numbers[right]
if(temp < target) {
left ++
} else if (temp > target) {
right --
} else {
return [left+1, right+1]
}
}
};
字符串反转
var reverseString = function (s) {
let left = 0
let right = s.length - 1
let swap = function (i, j) {
let temp = i
i = j
j = temp
}
while (left < right) {
[s[left], s[right]] = [s[right], s[left]];
left++
right--
}
return s
};
反转句子中单词
输入: s = "Let's take LeetCode contest"
输出: "s'teL ekat edoCteeL tsetnoc"
// 反转文字
var reverseString = function (s) {
let left = 0
let right = s.length - 1
while (left < right) {
[s[left], s[right]] = [s[right], s[left]];
left++
right--
}
return s
};
// 反转句子中的单词
var reverseWords = function (s) {
let left = 0
let right = s.length - 1
let arr = s.split(' ')
for (var i = 0; i < arr.length; i++) {
arr[i] = reverseString(arr[i].split('')).join('')
}
reverseString(arr)
return arr.join(' ')
};
查找链表中的中间节点
// 双指针-快慢指针
function midnode(head) {
let fast = slow = head
while(fast && fast.next) {
fast = fast.next.next
slow = slow.next
}
return slow
}
// 第一次循环获得链表长度,第二次循环到N/2返回结果
function midnode(head) {
let len = 0
let listnode1 = listnode2 = head
while(listnode1) {
listnode1 = listnode1.next
len++
}
let temp = 0
while(temp< Math.trunc(len/2)) {
temp++
listnode2 = head.next
}
return listnode2
}
删除链表中倒数N的节点
// 利用栈stack
function deleteNnode(head, n) {
let stack = new Array()
let listnode1 = head
while(listnode1) {
stack.push(listnode1)
listnode1 = listnode1.next
}
let k = n
while(k>0) {
k--
stack.pop()
}
let temp = stack.pop()
temp.next = temp.next.next
return temp
}
// 第一次循环得出长度,第二次在头部插入0形成新的链表在倒数n的位置之前循环
// 每次取next, 在利用引用类型的数据特点,操作temp相当于操作listNode
function deleteNnode(head, n) {
let cur = head
let length = 0
let listNode = new ListNode(0, head);
while (cur != null) {
cur = cur.next
length++
}
let k = 0
let temp = listNode
while (k != length - n) {
temp = temp.next
k++
}
temp.next = temp.next.next
return listNode.next
}
滑动窗口
查询字符串的最长子串
示例 1:
输入: s = "abcabcbb" 输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb" 输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 示例 3:
输入: s = "pwwkew" 输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
解法思路 定义一个set类型来接收,每次循环后set长度进行比较 取出最长的值就是答案 每一次循环,判断第i-1位置开始,直到遇到重复的值为止的set长度,同时删除上一次set的头部
function lengthOfLongestSubstring(s) {
let len = s.length
let i = 0, rk = -1
let set = new Set()
let ans = 0
for(i; i< len; i++) {
if(i!=0) {
set.delete(s.charAt(i))
}
while(rk< n -1 && !set.has(s.charAt(rk + 1 ))) {}
set.add(s.charAt(rk+1))
rk ++
}
ans = Math.max(ans, set.length)
}
return ans
}
判断字符串的排列
var checkInclusion = function(s1, s2) {
const n = s1.length, m = s2.length;
if (n > m) {
return false;
}
const cnt1 = new Array(26).fill(0);
const cnt2 = new Array(26).fill(0);
for (let i = 0; i < n; ++i) {
++cnt1[s1[i].charCodeAt() - 'a'.charCodeAt()];
++cnt2[s2[i].charCodeAt() - 'a'.charCodeAt()];
}
console.log(cnt1.toString(), cnt2.toString())
// if (cnt1.toString() === cnt2.toString()) {
// return true;
// }
// for (let i = n; i < m; ++i) {
// ++cnt2[s2[i].charCodeAt() - 'a'.charCodeAt()];
// --cnt2[s2[i - n].charCodeAt() - 'a'.charCodeAt()];
// if (cnt1.toString() === cnt2.toString()) {
// return true;
// }
// }
// return false;
};
深度优先、广度优先
图像渲染
// 深度优先渲染
function colorFill(image, sr, sc, color) {
let m = image.length
let n = image[0].length
let oldColor = image[sr][sc]
const fill = (i,j) => {
image[i][j] = color
if(i<0|| j<0 || i>=m|| j>=n || image[i][j]!=oldColor) {
return
}
fill(i-1,j)
fill(i,j-1)
fill(i+1,j)
fill(i,j+1)
}
fill(sr,sc)
return image
}
function fill(image, sr, sr, color) {
let m = image.length
let n = image[0].length
let oldColor = image[sr][sc]
let queue = [[sr,sc]]
if(oldColor == color) retrun image
while(queue.length) {
let [i,j] = queue.shift()
image[i][j] = color
if(i-1>=0 && image[i-1,j]== oldcolor) queue.push([i-1,j]);
if(i+1<=m && image[i+1,j]== oldcolor) queue.push([i+1,j]);
if(j-1>=0 && image[i,j-1]== oldcolor) queue.push([i,j-1]);
if(j+1>=0 && image[i,j+1]== oldcolor) queue.push([i,j+1]);
}
return image
}
计算岛屿最大面积
深度优先思路:
- 取出一点(i,j) 判断边界和值 如果超出边界或者为0 返回
- 通过1得出这个点是岛屿点,将这个点赋值为0
- 定义一个ans 通过递归调用从(i,j)点开始收集所有岛屿并令ans+1
- 遍历图 返回结果
var maxAreaOfIsland = function (grid) {
let m = grid.length
let n = grid[0].length
function dfs(i, j) {
if (i < 0 || i >= m || j < 0 || j >= n || grid[i][j] == 0) return 0
grid[i][j] = 0
let ans = 1, dm = [1,-1,0,0], dn = [0,0,1,-1]
for(let k = 0; k< dm.length; k++) {
ans = ans + dfs(i + dm[k], j + dn[k])
}
return ans
}
let res = 0
for(let i = 0; i< m; i++) {
for(let j =0 ; j< n; j++) {
res = Math.max(dfs(i,j), res)
}
}
return res
};
广度优先思路
var maxAreaOfIsland = function (grid) {
let m = grid.length
let n = grid[0].length
let res = 0
let dx= [1,-1,0,0], dy= [0,0,1,-1]
for(let i = 0; i< m; i++) {
for(let j =0 ; j< n; j++) {
let queue = [[i,j]]
let temp = 0
while(queue.length) {
let [x,y] = queue.shift()
if (x < 0 || x >= m || y < 0 || y >= n || grid[x][y] === 0) continue;
if(grid[x][y] == 1) {
grid[x][y] = 0
temp ++
for(let k = 0; k< dx.length; k++) {
queue.push([x+dx[k],y+dy[k]])
}
}
}
ans = Math.max(ans, temp)
}
}
return ans
}
合并二叉树
// dfs 递归调用
function mergeTree(root1, root2) {
if(root1 == null) return root2
if(root2 == null) return root1
return new treeNode(
root1.val + root2.val,
mergeTrees(root1.left, root2.left),
mergeTrees(root1.right, root2.right)
)
}
// bfs
/**
* @param {TreeNode} root1
* @param {TreeNode} root2
* @return {TreeNode}
*/
var mergeTrees = function (root1, root2) {
// 如果只要有一个二叉树为空,则合并后的二叉树为另一个非空的二叉树
if (root1 == null) return root2;
if (root2 == null) return root1;
// 两个二叉树都不为空的情况
let queue = [merged], queue1 = [root1], queue2 = [root2];
while(queue1.length && queue2.length) {
let node = queue.shift(),
node1 = queue1.shift(),
node2 = queue2.shift();
let left1 = node1.left,
left2 = node2.left,
right1 = node1.right,
right2 = node2.right;
if (left1 || left2) {
// 要合并俩节点有左子节点都非空
if (left1 && left2) {
// 合并并赋值为左子树
let left = new TreeNode(left1.val + left2.val);
node.left = left;
// 齐头并进入队列
queue.push(left);
queue1.push(left1);
queue2.push(left2);
} else if (left1) node.left = left1;
else if (left2) node.left = left2;
}
if (right1 || right2) {
if (right1 && right2) {
let right = new TreeNode(right1.val + right2.val);
node.right = right;
queue.push(right);
queue1.push(right1);
queue2.push(right2);
} else if (right1) node.right = right1;
else if (right2) node.right = right2;
}
}
};