算法九月算法打卡

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)为了九月秋招,现在开始面试打卡——第五天

OpenMMLab 实战营打卡 - 第 四 课 目标检测算法基础

打卡算法 18四数之和 算法解析

打卡算法 18四数之和 算法解析

打卡算法 16最接近的三数之和 算法解析

打卡算法 16最接近的三数之和 算法解析