算法九月算法打卡
Posted усил
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法九月算法打卡相关的知识,希望对你有一定的参考价值。
2022-09-01
外观数列
后一项是前一项的描述
获取第 n项数列,需要获取第n-1项数列。由此得出要采用递归回溯的形式
/**
* @param number n
* @return string
*/
var countAndSay = function(n)
if(n == 1) return "1";
// 上一串字符串
let prevSeq = countAndSay(n - 1);
// 返回结果
let res = "";
// 上一个数字
let lastNum = prevSeq.charAt(0);
// 出现的次数
let numCount = 0;
for (let i = 0; i < prevSeq.length; i++)
if (prevSeq.charAt(i) == lastNum)
++numCount;
else
res += numCount;
res += lastNum;
// 更新上一个数字
lastNum = prevSeq.charAt(i);
numCount = 1;
// 特殊情况
if (i == prevSeq.length - 1)
res += numCount;
res += lastNum;
return res;
;
组合总合
关键点:无重复,同一个数字可以无限制重复被选取
采用递归回溯的形式
1、将数组进行升序排序
2、遍历数组进行递归
- 关键:每次递归前需要判断当前数值是否小于目标值,小于则才可以添加进去
- 关键:当前数值进行递归结束后,需要将当前数值进行回溯(即去除该值)
3、递归结束的标志:目标值为0
/**
* @param number[] candidates
* @param number target
* @return number[][]
*/
var combinationSum = function(candidates, target)
// 升序
candidates.sort((a, b) => a - b);
// 结果
let res = [];
let dfs = function (start, target, comine)
// 满足条件
if (target == 0)
res.push([...comine])
for(let i = start; i < candidates.length; i++)
// 当前值大于目标值,无需添加
if (target < candidates[i]) return;
// 该值可能满足条件
comine.push(candidates[i]);
dfs(i, target - candidates[i], comine);
comine.pop(); // 回溯
dfs(0, target, []);
return res;
;
2022-09-02
组合总和II
关键点:每一个数字只能使用一次
实现逻辑跟上面的一致,只不过在递归前需要添加一个判断条件
当前位置的数值等于前一个数值时,并且当前数值位置要大于start,则该值不能添加进去
if (i > start && candidates[i] == candidates[i - 1]) continue
/**
* @param number[] candidates
* @param number target
* @return number[][]
*/
var combinationSum2 = function(candidates, target)
candidates.sort((a, b) => a - b);
let res = [];
let dfs = function (start, target, combin)
// 剪枝
if (target == 0) res.push([...combin]);
for(let i = start; i < candidates.length; i++)
if (candidates[i] > target) break;
// 打头元素不能相同,不然重复
if (i > start && candidates[i] === candidates[i - 1])continue;
combin.push(candidates[i]);
dfs(i+1, target - candidates[i], combin);
combin.pop();
dfs(0, target, []);
return res;
;
组合总和III
实现逻辑跟组合总和III一致
/**
* @param number k
* @param number n
* @return number[][]
*/
var combinationSum3 = function(k, n)
let candidates = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let res = [];
let dfs = function(start, target, combin)
if (combin.length == k && target == 0)
res.push([...combin]);
return;
for(let i = start; i < candidates.length; i++)
if(candidates[i] > target) break;
if (i > start && candidates[i] == candidates[i - 1]) continue;
combin.push(candidates[i])
dfs(i + 1, target - candidates[i], combin);
combin.pop();
dfs(0, n, []);
return res;
;
2022-09-03
解数独
1、需要实现 isValid() 判断当前填入值后,当前数独是否有效。
2、从 1 到 9 不断去尝试填入的值是否有效
/**
* @param character[][] board
* @return void Do not return anything, modify board in-place instead.
*/
var solveSudoku = function (board)
function isValid(row, col, val, board)
// 行不能重复
for (let i = 0; i < 9; i++)
if (board[row][i] === val) return false
// 列不能重复
for (let i = 0; i < 9; i++)
if (board[i][col] === val) return false
let boxRow = Math.floor(row / 3) * 3
let boxCol = Math.floor(col / 3) * 3
for (let i = boxRow; i < boxRow + 3; i++)
for (let j = boxCol; j < boxCol + 3; j++)
if (board[i][j] === val) return false
return true
let helper = function ()
for (let i = 0; i < 9; i++)
for (let j = 0; j < 9; j++)
if (board[i][j] !== ".") continue;
// 不断尝试
for (let val = 1; val <= 9; val++)
if (isValid(i, j, `$val`, board))
board[i][j] = `$val`
if (helper()) return true;
// 当前位置 board[i][j] 不能填入数字 val
board[i][j] = "."
return false;
return true;
helper();
return board;
;
接雨水
1、左右指针,左指针在最左边,右指针在最右边,两者不断向中间靠拢
2、移动前需要判断 当前左指针指向的位置height[l],与当前保存的左边界最大值lmax进行比较,并保存最大值
3、右指针同理
4、此时若 左边界(lmax)小于右边界(rmax),则左边界向中间移动。反之,右向中间移动
5、移动过程中计算当前位置接到的雨水
res += (lmax - height[l]) lmax < rmax
res += (rmax - height[r]) rmax <= lmax
/**
* @param number[] height
* @return number
*/
var trap = function(height)
let res = 0;
let l = 0;
let r = height.length - 1;
let lmax = 0; // 左边最大值
let rmax = 0; // 右边最大值
while(l < r)
// 更新最大值
lmax = Math.max(lmax, height[l]);
rmax = Math.max(rmax, height[r]);
if (lmax < rmax) // 左边短于右边
res += (lmax - height[l])
l++;
else // 右边短于左边
res += (rmax - height[r])
r--;
return res;
;
2022-09-04
缺失的第一个正数
题意是根据所给数组中没有出现的最小正整数。
解法:
- 创建 nums.length 个桶,每一个桶对应存发该位置应该存放的数字(
i+1 == num
) - 最后遍历所有桶,那个桶为空,说明缺少的正整数为
i + 1
交换的必须满足以下几个条件:
- 交换值val 必须在
val > 0 && val <= len
;
/**
* @param number[] nums
* @return number
*/
var firstMissingPositive = function(nums)
let len = nums.length;
let swap = function(nums, i, j)
let temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
// 将每一个值找到对应桶的位置
for (let i= 0; i < len;)
let val = nums[i];
if (val > 0 && val <= len && val != i + 1 && nums[val - 1] != val)
swap(nums, i, val - 1);
else
i++;
// 找每一个桶是否位置对应
for(let i = 0; i < len; i++)
if (nums[i] != i + 1) return i + 1;
return len + 1;
;
字符串相乘
字符串相乘
关键点:
- 对应位置相乘的值对应放入的位置为(i + j),进位为(i + j + 1)
- 计算结束后,需要判断结果数组第一位res[0]是否为0,为0需要删除
/**
* @param string num1
* @param string num2
* @return string
*/
var multiply = function(num1, num2)
if (num1 == '0' || num2 == '0') return '0';
let len1 = num1.length;
let len2 = num2.length;
// 结果数组
let res = new Array(len1 + len2).fill(0);
for (let i = len1 - 1; i >= 0; i--)
for (let j = len2 - 1; j >= 0; j--)
const mul = num1[i] * num2[j];
// 乘积在结果数组的位置
const p1 = j + i;
// 进位位置
const p2 = i + j + 1;
const sum = res[p2] + mul;
res[p1] += Math.floor(sum / 10);
res[p2] = sum % 10
if (res[0] == 0) res.shift()
return res.join("")
;
2022-09-05
跳跃游戏
/**
* @param number[] nums
* @return boolean
*/
var canJump = function(nums)
let len = nums.length;
// 距离
let distance = len - 1;
// 倒数第二个开始
let last = len - 2;
for (let i = last; i >= 0; i--)
// nums[i] + i 代表当前位置(i)能够到达最远右边的距离
if (nums[i] + i >= distance)
// 进入到这里,说明当前 i 可以到达最右边
// 接着distance更新为(最左边到达i的距离)
distance = i;
// 判断i之前有哪些点可以到达 i,由此循环
// 遍历完数组, distance 为 0 说明可以进行跳跃
return distance === 0;
跳跃游戏II
/**
* @param number[] nums
* @return number
*/
var jump = function(nums)
// 最远距离
let maxPos = 0;
// 最远点
let end = 0;
// 步长
let ans = 0;
for(let i = 0; i < nums.length - 1; i++)
maxPos = Math.max(maxPos, nums[i] + i);
if (i == end) // 到达最远边界
end = maxPos;
ans++;
return ans;
;
2022-09-06
全排列
/**
* @param number[] nums
* @return number[][]
*/
var permute = function (nums)
let res = [];
let dfs = function (nums, tmp, visited)
if (tmp.length == nums.length)
res.push([...tmp]);
return;
for (let i = 0; i < nums.length; i++)
if (visited[i] == 1) continue;
visited[i] = 1;
tmp.push(nums[i]);
dfs(nums, tmp, visited);
visited[i] = 0;
tmp.pop();
dfs(nums, [], []);
return res;
;
全排列II
var permuteUnique = function(nums)
const ans = [];
const vis = new Array(nums.length).fill(false)为了九月秋招,现在开始面试打卡——第五天