js解leetcode(29)-中等

1.消除游戏

题目:

给定一个从1 到 n 排序的整数列表。
首先,从左到右,从第一个数字开始,每隔一个数字进行删除,直到列表的末尾。
第二步,在剩下的数字中,从右到左,从倒数第一个数字开始,每隔一个数字进行删除,直到列表开头。
我们不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。
返回长度为 n 的列表中,最后剩下的数字。

思路:可以假定一个步长,和一个方向,每一次循环操作之后,步长相当于乘以2,去掉步长上的元素

时间复杂度O(n),空间复杂度O(1)

/**
 * @param {number} n
 * @return {number}
 */
var lastRemaining = function(n) {
    //我们只需要记住每次删除数字后开头的数字是几就可以了
    let flag = false;//false表示从左往右,true表示从右往左
    let res = 1;
    let step = 1;
    let num = n;//剩下数字的个数
    while(res+step<=n){
        if(num%2===0){ res = flag===false?(res+step):res; }//剩下偶数个数字
        else{//剩下奇数个数字
            res +=step;
        }
        step = step*2;//更新步长
        flag = !flag;//更新删除方向
        //更新剩下数字的个数
        num = Math.floor(num/2);
    }
    return res;

};

2.至少有K个重复字符的最长子串

题目:找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 的长度。

思路:每次遍历字符串,先找到所有出现次数少于k的字符,那么结果肯定是在以这些字符分隔的子字符串中,所以这是一个递归问题。在每一轮递归中记录那些字符的下标,然后分隔,进入下一轮递归

时间复杂度:O(n2),空间复杂度O(n)

/**
 * @param {string} s
 * @param {number} k
 * @return {number}
 */
var longestSubstring = function(s, k) {
  const l = s.length;
  if (l < k) return 0;
  const map = new Map();
  for (const n of s) {
    map.set(n, (map.get(n) || 0) + 1);
  }
  const res = [];
  for (let i = 0; i < l; i++) {
    if (map.get(s[i]) < k) {
      res.push(i);
    }
  }
  if (!res.length) return s.length;
  const l1 = res.length;
  const v = [];
  v.push(longestSubstring(s.slice(0, res[0]), k));

  for (let i = 1; i < l1; i++) {
    v.push(longestSubstring(s.slice(res[i - 1] + 1, res[i]), k));
  }
  v.push(longestSubstring(s.slice(res[l1 - 1] + 1, l), k));
  return Math.max(...v);
};

3.旋转函数

题目:

给定一个长度为 n 的整数数组 A 。

假设 Bk 是数组 A 顺时针旋转 k 个位置后的数组,我们定义 A 的“旋转函数” F 为:

F(k) = 0 * Bk[0] + 1 * Bk[1] + ... + (n-1) * Bk[n-1]。

计算F(0), F(1), ..., F(n-1)中的最大值。

思路:错位相减。

假定起始值是:a0 * 0 + a1* 1 + ...+ an-1 * n-1,那么旋转之后的下一个值是什么?

是a0*1 + a1*2 + ... + an-1*0,相对于上一个,可以假定右移,即每一个成员都加上自身,然后减去当前n*最后一个成员。

所以,先计算数组的累加和,然后在每一轮旋转时,加上累加和,减去这一轮的最后一个元素*数组长度

时间复杂度O(n),空间复杂度O(1)

/**
 * @param {number[]} A
 * @return {number}
 */
var maxRotateFunction = function(A) {
  let sum=0; temp=0;
  for (let i = 0; i < A.length; i++) {
    temp += i * A[i];
    sum += A[i];
  }
  let maxR = temp;
  for (let i = A.length - 1; i > 0; i--) {
    temp = sum - A.length * A[i] + temp;
    maxR = temp > maxR ? temp : maxR;
  }
  return maxR

};

4.整数替换

题目:

给定一个正整数 n ,你可以做如下操作:

如果 n 是偶数,则用 n / 2替换 n 。
如果 n 是奇数,则可以用 n + 1或n - 1替换 n 。
n 变为 1 所需的最小替换次数是多少?

思路:用map记录每个数字对应的结果。如果n是偶数,那么map[n]=map[n/2]+1,如果n是奇数,那么map[n]=Math.min(map[n+1],map[n-1])+1,而map[n+1]和map[n-1]又可以用递归求,

时间复杂度O(n),空间复杂度O(n)

/**
 * @param {number} n
 * @return {number}
 */
var integerReplacement = function(n) {
  const map = {1:0};
  const search = (n) => {
    if (n == 1) return 0;
    if (map[n]) return map[n];
    if (n % 2) {
      const v = 1 + Math.min(search(n + 1), search(n - 1));
      map[n] = v;
    } else {
      const v = search(n / 2) + 1;
      map[n] = v;
    }
    return map[n];
  };
 return search(n);
};

5.随机数索引

题目:

给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引。 您可以假设给定的数字一定存在于数组中。

注意:
数组大小可能非常大。 使用太多额外空间的解决方案将不会通过测试。

思路:记录每个数字的下标,用数组存放,然后随机获取数组下标

时间复杂度O(n),空间复杂度O(n)

/**
 * @param {number[]} nums
 */
var Solution = function (nums) {
  this.map = new Map();
  const l = nums.length;
  for (let i = 0; i < l; i++) {
    if (this.map.has(nums[i])) {
      this.map.get(nums[i]).push(i);
    } else {
      this.map.set(nums[i], [i]);
    }
  }
};

/**
 * @param {number} target
 * @return {number}
 */
Solution.prototype.pick = function (target) {
  const res = this.map.get(target);
  const index = ~~(Math.random() * res.length);
  return res[index];
};

/**
 * Your Solution object will be instantiated and called as such:
 * var obj = new Solution(nums)
 * var param_1 = obj.pick(target)
 */

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值