leetcode-数组相关

数组

全排列重复

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permute = function(nums) {
    let res = [],path=[],used=[]
    track()
    function track(){
        if(path.length === nums.length){
            res.push(Array.from(path))
        }
        for(let i = 0;i < nums.length;i++){
            if(used[i]){
                continue
            }
            used[i] = true
            path.push(nums[i])
            track()
            used[i] = false
            path.pop(nums[i])
        }
    }
    return res
};

全排列不重复

var permuteUnique = function (nums) {
    let res = [], path = []
    nums.sort((x, y) => x - y);
    function track(nums, k, used) {
        if (nums.length === path.length) {
            res.push(Array.from(path))
            return
        }
        for (let i = 0; i < k; i++) {
        //当前元素使用过或者当前元素的值等于前一个元素的值,前一个元素也使用过则跳过
            if (used[i] || i > 0 && nums[i] === nums[i - 1] && used[i - 1] === true) continue
            path.push(nums[i])
            used[i] = true
            track(nums, k, used)
            used[i] = false
            path.pop()
        }
    }
    track(nums, nums.length, [])
    return res
};

电话号码组合

var letterCombinations = function (digits) {
    let map = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"]
    let path = [], res = []
    if(digits.length === 0) return []
    if(digits.length === 1) return map[digits].split("");
    function track(a) {
        if (path.length === digits.length) {
            res.push(path.join(""));
            return;
        }
        for (const v of map[digits[a]]) {
            path.push(v);
            track(a + 1);
            path.pop();
        }

    }
    track(0)
    return res
};

组合问题

在这里插入图片描述

var combine = function(n, k) {
    let res = [],path = []
    function track(start){
        if(k === path.length){
            res.push(Array.from(path))
        }
        for(let i = start;i <= n;i++){
        	//没找到一个push进去
            path.push(i)
            //从i+1找
            track(i+1)
            //上级找完pop
            path.pop()
        }
    }
    track(1)
    return res
};

组合求和可重复

在这里插入图片描述

var combinationSum = function(candidates, target) {
    let res = [],path = []
    function track(start,sum){
        if(sum > target){
            return
        }
        if(sum === target){
            res.push(Array.from(path))
        }
        for(let i = start;i < candidates.length;i++){
            path.push(candidates[i])
            track(i,sum+candidates[i])
            path.pop()
        }
    }
    // 最开始可选的数是从第0项开始的,传入一个空集合,sum也为0
    track(0,0)
    return res
};

在这里插入图片描述

组合求和不重复

const combinationSum2 = (candidates, target) => {
  candidates.sort((a,b) => a - b ); // 升序排序
  const res = [];
  const dfs = (start, temp, sum) => { // start是索引 当前选择范围的第一个
    if (sum >= target) {        // 爆掉了,不用继续选了
      if (sum == target) {      // 满足条件,加入解集
        res.push(temp.slice()); // temp是引用,所指向的内存后续还要操作,所以拷贝一份
      }
      return;                   // 结束当前递归
    }
    for (let i = start; i < candidates.length; i++) { // 枚举出当前的选择
    // 当前选项和左邻选项一样,跳过
      if (i - 1 >= start && candidates[i - 1] == candidates[i]) { 
        continue;
      }
      temp.push(candidates[i]);     // 作出选择
      dfs(i + 1, temp, sum + candidates[i]); // 基于该选择,继续选择,递归
      temp.pop();    // 上面的递归结束,撤销选择,回到选择前的状态,切入另一分支
    }
  };

  dfs(0, [], 0);
  return res;
};

组合数三

在这里插入图片描述

const combinationSum3 = (k, n) => {
  const res = []; 
  // 基于当前已选的comb数组(和为sum),在数start到数9中继续选
  const dfs = (start, comb, sum) => { 
    if (comb.length == k) {     // 选够k个数 结束递归
      if (sum == n) {           // 组合中数之和等于n
        res.push(comb.slice()); // 将它的拷贝加入解集
      }
      return;
    }
    for (let i = start; i <= 9; i++) { // 枚举出所有的选择(选项)
      comb.push(i);                    // 作出一个选择i
      dfs(i + 1, comb, sum + i);       // 基于该选择i,往下递归
      comb.pop();                      // 撤销这个选择
    }
  };

  dfs(1, [], 0);  // 入口
  return res;
};

括号生成

var generateParenthesis = function (n) {
  const res = [];

  const dfs = (lRemain, rRemain, str) => { // 左右括号所剩的数量,str是当前构建的字符串
    if (str.length == 2 * n) { // 字符串构建完成
      res.push(str);           // 加入解集
      return;                  // 结束当前递归分支
    }
    if (lRemain > 0) {         // 只要左括号有剩,就可以选它,然后继续做选择(递归)
      dfs(lRemain - 1, rRemain, str + "(");
    }
    if (lRemain < rRemain) {   // 右括号比左括号剩的多,才能选右括号
      dfs(lRemain, rRemain - 1, str + ")"); // 然后继续做选择(递归)
    }
  };

  dfs(n, n, ""); // 递归的入口,剩余数量都是n,初始字符串是空串
  return res;
};

分割回文串

在这里插入图片描述

var partition = function (s) {
    const res = []; 

    function dfs(temp, start) { 
        if (start == s.length) {
            res.push(temp.slice());
            return;
        }
        for (let i = start; i < s.length; i++) {
            if (isPali(s, start, i)) {
                temp.push(s.substring(start, i + 1));
                dfs(temp, i + 1);
                temp.pop();
            }
        }
    }
    dfs([], 0); 	
    return res;
};

function isPali(s, l, r) {
    while (l < r) {
        if (s[l] != s[r]) {
            return false;
        }
        l++;
        r--;
    }
    return true;
}

子集

在这里插入图片描述

var subsets = function(nums) {
    let res = [],path = []
    function track(start){
        res.push(Array.from(path))
        for(let i = start;i < nums.length;i++){
            path.push(nums[i])
            track(i+1)
            path.pop(nums[i])
        }
    }
    track(0)
    return res
};

三数之和

var threeSum = function (nums) {
    let res = []
    nums.sort((x, y) => x - y)
    for (let i = 0; i < nums.length - 2; i++) {
        let left = i + 1, right = nums.length - 1
        if (nums[0] > 0) {
            break
        }
        if (i - 1 >= 0 && nums[i] === nums[i - 1]) {
            continue
        }
        while (left < right) {
            let sum = nums[i] + nums[left] + nums[right]
            if (sum > 0) {
                right--
            } else if (sum < 0) {
                left++
            } else {
                res.push([nums[i],nums[left],nums[right]])
                while(left < right && nums[right] === nums[--right]);
                while(left < right && nums[left] === nums[++left]);
            }
        }
    }
    return res
};

最接近的三数之和

var threeSumClosest = function (nums, target) {
    if(nums.length === 3) return nums[0]+nums[1]+nums[2]
    nums= nums.sort((a,b)=> a - b)
    let res
    let min = Infinity
    for (let i = 0; i <= nums.length - 3; i++) {
        let basic = nums[i]
        let left = i + 1
        let right = nums.length - 1
        while (left < right) {
            let sum = basic + nums[left] + nums[right] //三数之和
            let diff = Math.abs(sum - target) //最小查
            if (diff < min) {
                min = diff
                res = sum
            }
            if (sum < target) {
                left++
            } else {
                right--
            }
        }
    }
    return res
};

旋转排序数组-无重复

const search = (nums, target) => {
    let [left, right] = [0, nums.length - 1];
    while (left <= right) {
        const mid = (left + right) >> 1;
        if (nums[mid] === target) return mid;
        if (nums[left] < nums[mid]) {
            // 左边是升序的
            if (nums[left] <= target && target <= nums[mid]) {
                // target在升序的里面
                right = mid - 1;
            } else {
                // target不在升序的里面
                left = mid + 1;
            }
        } else {
            // 右边升序
            if (nums[mid] <= target && target <= nums[right]) {
                // target在升序的里面
                left = mid + 1;
            } else {
                // target不在升序的里面
                right = mid - 1;
            }
        }
    }
    return nums[left + 1] === target ? left + 1 : -1;
};

旋转排序数组有重复

var search = function(nums, target) {
    const n = nums.length;
    if (n === 0) {
        return false;
    }
    if (n === 1) {
        return nums[0] === target;
    }
    let l = 0, r = n - 1;
    while (l <= r) {
        const mid = Math.floor((l + r) / 2);
        if (nums[mid] === target) {
            return true;
        }
        if (nums[l] === nums[mid] && nums[mid] === nums[r]) {
            ++l;
            --r;
        } else if (nums[l] <= nums[mid]) {
            if (nums[l] <= target && target < nums[mid]) {
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        } else {
            if (nums[mid] < target && target <= nums[n - 1]) {
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
    }
    return false;
};

螺旋矩阵

var spiralOrder = function (matrix) {
    if (matrix.length == 0) return []
    const res = []
    let top = 0, bottom = matrix.length - 1, left = 0, right = matrix[0].length - 1
    const size = matrix.length * matrix[0].length
    while (res.length !== size) { // 仍未遍历结束
        for (let i = left; i <= right; i++) res.push(matrix[top][i])
        top++
        for (let i = top; i <= bottom; i++) res.push(matrix[i][right])
        right--
        if (res.length === size) break // 遍历结束
        for (let i = right; i >= left; i--)  res.push(matrix[bottom][i])
        bottom--
        for (let i = bottom; i >= top; i--) res.push(matrix[i][left])
        left++
    }
    return res
};

旋转图像

var rotate = function(matrix) {
    const n = matrix.length;
    // 水平翻转
    for (let i = 0; i < Math.floor(n / 2); i++) {
        for (let j = 0; j < n; j++) {
            [matrix[i][j], matrix[n - i - 1][j]] = [matrix[n - i - 1][j], matrix[i][j]];
        }
    }
    // 主对角线翻转
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < i; j++) {
            [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
        }
    }
};

砖墙

var leastBricks = function (wall) {
    let map = new Map() //存放缝隙
    let height = wall.length
    let res = height
    for (let i = 0; i < height; i++) {
        let sum = 0
        //每次层的缝隙全部放进来
        for (let item of wall[i]) {
            sum += item
            if (map.has(sum)) {
                map.set(sum,map.get(sum)+1)
            } else {
                map.set(sum,1)
            }
        }
        //删除每一层最右边的缝隙
        map.delete(sum)
        sum = 0
    }
    //找到缝隙最多的
    for(let [x,y] of map){
        res = Math.min(res,height-y)
    }
    return res
};

合并区间

var merge = function(intervals) {
    let res = []
    intervals.sort((x,y)=>x[0]-y[0])
    let start = intervals[0]
    for(let i = 0;i < intervals.length;i++){
        let cur = intervals[i]
        if(start[1] >= cur[0]){
            start[1] = Math.max(start[1],cur[1])
        }else{
            res.push(start)
            start = cur
        }
    }
    res.push(start)
    return res
};

js排序方式

let arr = [30,10,111,35,1899,50,45]
arr.sort((x,y)=>{
    return x-y
})
console.log(arr)
let arr = [[2,1],[2,6],[1,5],[1,9],[3,1]]
arr.sort((x,y)=>{
    if(x[0] === y[0]){
        return x[1] - y[1]
    }else{
        return x[0] - y[0]
    }
})
//[ [ 1, 5 ], [ 1, 9 ], [ 2, 1 ], [ 2, 6 ], [ 3, 1 ] ]
console.log(arr)

快排

let arr = [5,6,1,2,3,5,8,9,1,55]

function quickSort(arr,left,right){
    if(left < right){
        let positions = position(arr,left,right)
        quickSort(arr,left,positions-1)
        quickSort(arr,positions + 1,right)
    }
}
function position(arr,left,right){
    let tmp = arr[left]
    while(left < right){
        while(left < right && arr[right] >= tmp){
            right --;
        }
        arr[left] = arr[right]

        while(left < right && arr[left] <= tmp){
            left ++;
        }
        arr[right] = arr[left]
    }
    arr[left] = tmp
    return left
}
quickSort(arr,0,arr.length-1)
console.log(arr)

topK

topK快排思路大

/**
 * @param {number[]} arr
 * @param {number} k
 * @return {number[]}
 */
var getLeastNumbers = function(arr, k) {
    quicksort(arr,0,arr.length-1,k)
    return arr.splice(0,k)
};
function quicksort(arr,left,right,k){
    if(left < right){
        let position = getPos(arr,left,right,k);
        if(position == k){
            return
        }else if(k < position){
            quicksort(arr,left,position-1,k)
        }else{
            quicksort(arr,position+1,right,k)
        }
    }
}
function getPos(arr,left,right,k){
    let tmp = arr[left]

    while(left < right){
        while(left < right && arr[right] >= tmp){
            right--
        }
        arr[left] = arr[right]

        while(left < right && arr[left] <= tmp){
            left++
        }
        arr[right] = arr[left]
    }
    arr[left] = tmp
    return left
}

topK堆排序思路大

topk大

var getLeastNumbers = function (arr, k) {
    return headSort(arr, k)
};
function headSort(arr, k) {
    let len = arr.length
    for (let i = Math.floor(len / 2) - 1; i >= 0; i--) {
        adjust(arr, i, len)
    }
    // for (let j = arr.length - 1; j >= 0; j--) {
    //     swap(arr, 0, j)
    //     adjust(arr, 0, j)
    // }
    let resultArray = []
    for(let i = 1; i <= k; i++){
        resultArray.push(arr[0])
        swap(arr, 0, len - i)
        adjust(arr, 0, len - i)
    }
    return resultArray
}
function adjust(arr, i, len) {
    let tmp = arr[i]
    for (let m = 2*i+1;m < len;m = 2*m+1) {
        if(m+1 < len && arr[m] < arr[m+1]){
            m++
        }
        if (arr[m] > arr[i]) {
            arr[i] = arr[m]
            i = m
        } else {
            break
        }
        arr[i] = tmp
    }
}
function swap(arr, i, j) {
    let tmp = arr[i]
    arr[i] = arr[j]
    arr[j] = tmp
}

小镇法官

var findJudge = function(n, trust) {
    if(n == 1) return 1
    let result = new Array(n+1).fill(0)
    //根据下标记录每个人的信任次数
    for(let i = 0;i < trust.length;i++){
        result[trust[i][0]]--
        result[trust[i][1]]++ 
    }
    //信任次数 = n-1的人的下标就是
    for(let i = 0;i < result.length;i++){
        if(result[i] === n-1) return i
    }
    return -1
};

旋转数组

const search = (nums, target) => {
    let [left, right] = [0, nums.length - 1];
    while (left <= right) {
        const mid = (left + right) >> 1;
        if (nums[mid] === target) return mid;
        if (nums[left] < nums[mid]) {
            // 左边是升序的
            if (nums[left] <= target && target <= nums[mid]) {
                // target在升序的里面
                right = mid - 1;
            } else {
                // target不在升序的里面
                left = mid + 1;
            }
        } else {
            // 右边升序
            if (nums[mid] <= target && target <= nums[right]) {
                // target在升序的里面
                left = mid + 1;
            } else {
                // target不在升序的里面
                right = mid - 1;
            }
        }
    }
    return nums[left + 1] === target ? left + 1 : -1;
};

非递减数列

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var checkPossibility = function(nums) {
    let count=0
    for(let i=0;i<=nums.length-2;i++){
    //上一个值、当前值、下一个值设为before、cur、next
        let before=nums[i-1], cur=nums[i],next=nums[i+1];
       // 当next>=before,为了不破坏下一次判断,我们令cur=next,这样cur既大于等于before,也不会影响下一个值
	//当next<before,那我们就不能修改cur值了,因为这样会使得cur<before,因此我们令next=cur,然后在下次循环中判断可不可行
        if(next<cur){
            if(next>=before||before===undefined){
                
            }else{
                nums[i+1]=cur;
            }
            count++;
        }
        if(count>1){
            return false;
        }
    }

    return true;
};

二分查找有重复数的有序数组

function search( nums ,  target ) {
    let left = 0,right = nums.length-1
    let res = -1
    while(left <= right){
        let mid = (left + right) >> 1
        if(nums[mid] === target){
            res = mid
            right = mid - 1
        }else if(nums[mid] < target){
            left = mid +1
        }else{
            right = mid -1
        }
    }
    return res
}

只出现一次的数

在这里插入图片描述


var singleNumber = function(nums) {
    let ans = 0;
    for(const num of nums) {
        ans ^= num;
    }
    return ans;
};

分糖果

在这里插入图片描述

var distributeCandies = function(candyType) {
    candyType.sort((x,y)=>x-y)
    let count = 1
    for(let i = 1;i < candyType.length;i++){
        if(candyType[i] !== candyType[i-1] && count < Math.floor(candyType.length/2)){
            count++
        }
    }
    return count
};

数组中超过一半的数

var majorityElement = function(nums) {
    let count = 1;
    let majority = nums[0];
    for(let i = 1; i < nums.length; i++) {
        if (count === 0) {
            majority = nums[i];
        }
        if (nums[i] === majority) {
            count ++;
        } else {
            count --;
        }
    }
    return majority;
};

六个数最大时间


function getTime(time) {
    let flag = 'invalid'
    let result = []
    let data1 = getDataOfLocation(list, 3);
    if (data1 != -1) {
        list.splice(list.indexOf(data1), 1)
        result.push(data1)
    } else {
        return flag;
    }
    //如果第一位是2,那么第二位则不能超过4
    if (result[0] == '2') {
        //第二位
        let data2 = getDataOfLocation(list, 4);
        if (data2 != -1) {
            // 按照元素删除
            list.splice(list.indexOf(data2), 1)
            result.push(data2);
        } else {
            return flag;
        }
        // 否则,第一位可能是0或者1,这样第二位可以是0-9,即小于10
    } else {
        //第二位
        let data2_t = getDataOfLocation(list, 10);
        if (data2_t != -1) {
            list.splice(list.indexOf(data2_t), 1)
            result.push(data2_t);
        } else {
            return flag;
        }
    }

    //第三位,分钟最大是59,即小于6
    let data3 = getDataOfLocation(list, 6);
    if (data3 != -1) {
        list.splice(list.indexOf(data3), 1)
        result.push(data3);
    } else {
        return flag;
    }

     //第四位,0-9
    let data4 = getDataOfLocation(list, 10);
    if (data4 != -1) {
        list.splice(list.indexOf(data4), 1)
        result.push(data4);
    } else {
        return flag;
    }

    //第五位
    let data5 = getDataOfLocation(list, 6);
    if (data5 != -1) {
        list.splice(list.indexOf(data5), 1)
        result.push(data5);
    } else {
        return flag;
    }
    //最后一位
    if (getDataOfLocation(list, 10) != -1) {
        result.push(getDataOfLocation(list, 10));
    } else {
        return flag;
    }
    return result
}

function getDataOfLocation(list, standard) {

    let arr = list.filter((x) => {
        return x < standard
    })
    if (arr.length === 0) {
        return -1
    }
    let max = Math.max(...arr)
    return max
}
let list = [0, 2, 3, 0, 5, 6]
getTime(list)

删除有序数组中的重复数

var removeDuplicates = function(nums) {
    let left = 1,right = 1
    while(right < nums.length){
        if(nums[right] !== nums[right-1]){
            nums[left] = nums[right]
            left++
        }
        right++
    }
    return left
};

移除数组中指定的元素

var removeElement = function(nums, val) {
    let left = 0
    for(let i = 0;i < nums.length;i++){
        if(nums[i] !== val){
            nums[left] = nums[i]
            left ++
        }
    }
    return left
};

数组+1

var plusOne = function(digits) {
    for (let i = digits.length - 1; i >= 0; i--) {
        if (digits[i] !== 9) {
            digits[i]++;
            // 不为9,加1后直接返回
            return digits;
        } else {
            // 当前位为9时,把当前位置为0,继续循环会进行进位操作
            digits[i] = 0;
        }
    }
  
    // 当遍历结束了,且数组是99、999... 等特殊情况,在开头添加1
    digits.unshift(1);
    return digits;
};

数组形式的整数加法

/**
 * @param {number[]} num
 * @param {number} k
 * @return {number[]}
 */
var addToArrayForm = function (num, k) {
    let i = num.length - 1
    let flag = 0
    let res = []
    while (i >= 0 || k !== 0) {
        let x = num[i] === undefined ? 0 : num[i]
        let y = k % 10
        let sum = flag + x + y
        res.unshift(sum % 10)
        flag = Math.floor(sum / 10)
        k = Math.floor(k / 10)
        i--
    }
    if (flag === 1) {
        res.unshift(1)
    }
    return  res
};

兄弟单词

let train = ['abc' ,'bca' ,'cab'] 
let test = 'abc'

function isBrother(a,b){
    if(a === b){
        return false
    }else{
        console.log(a.split('').sort(),b.split('').sort())
        if(a.split('').sort().join('') === b.split('').sort().join('')){
            return true
        }else{
            return false
        }
    }
}
let count = 0
for(let i = 0;i < train.length;i++){
    if(isBrother(train[i],test)){
        count ++
    }
}
console.log(count)

扑克牌中的顺子

在这里插入图片描述

class Solution {
    public boolean isStraight(int[] nums) {
        Set<Integer> repeat = new HashSet<>();
        int max = 0, min = 14;
        for(int num : nums) {
            if(num == 0) continue; // 跳过大小王
            max = Math.max(max, num); // 最大牌
            min = Math.min(min, num); // 最小牌
            if(repeat.contains(num)) return false; // 若有重复,提前返回 false
            repeat.add(num); // 添加此牌至 Set
        }
        return max - min < 5; // 最大牌 - 最小牌 < 5 则可构成顺子
    }
}

根据身高重建队列

/**
 * @param {number[][]} people
 * @return {number[][]}
 */
var reconstructQueue = function (people) {
    // 将people按身高从大到小排序,如果身高一样则将前面高于自己人数小的人放在前面
    people.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : b[0] - a[0])
    // 创建新数组 ans
    let ans = []
    for (let i = 0; i < people.length; i++) {
        // 挨个根据前面高于自己人数插入到ans里
        // 因为people已按照身高排序,所以某个人被插入到ans里时,所有比他高的都已经在ans里了
        // 而身高比他矮的人怎样插入到ans里都不影响前面高于他的人数
        // 所以这样得到的数组就是符合我们要求的队列
        ans.splice(people[i][1],0,people[i])
    }
    return ans
};

单词的压缩编码

/**
 * @param {string[]} words
 * @return {number}
 */

/**
 * 暴力破解:
 *  1. 先根据单词长度排序(降序)
 *  2. 在根据indexOf判断,得到压缩后的S,返回S的长度
 */
var minimumLengthEncoding = function(words) {
    let S = ''
    words = words.sort( (a,b)=>b.length - a.length)
    for( let i = 0; i < words.length; i++ ){
        const word = words[i]
        const index = S.indexOf( word + '#' )
        if( !~index ) {
            S += `${word}#`
        }
    }
    return S.length
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值