leetcode刷题记录(3)

1.移除元素

题目:

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

和昨天的重复排序类似。

思路:单次遍历,并声明一个变量记录当前有效的长度,比较时,如果相等则直接进入下一轮循环,如果不相等,先把当前元素赋值给当前变量下标,然后变量自增1,(顺序不能弄错)

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

没啥优化空间,单次遍历,也没递归,时间复杂度和空间复杂度都是最低了。

2.实现strStr()

题目:

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1。

思路:其实就是字符串的indexOf方法,不过咱肯定用原生写。

和冒泡排序十分类似,。

思路:双重循环,依次比较

var strStr = function(haystack, needle) {
  let l = needle.length;
  if (!l) return l;
  let l2 = haystack.length;
  if (l > l2) return -1;
  for (let i = 0; i < l2; i++) {
    for (let j = 0; j < l; j++) {
      if (haystack[i + j] !== needle[j]) break;
      if (j === l - 1) {
        return i;
      }
    }
  }
  return -1;
};

问题:每个都遍历,耗时太长

优化方向:提早跳出不必要的循环。可以在外层循环比较haystack剩余字符串长度和needle的长度,如果前者更小,则直接跳出循环返回-1即可。

var strStr = function(haystack, needle) {
  let l = needle.length;
  if (!l) return l;
  let l2 = haystack.length;
  if (!l2) return -1;
  if (l > l2) return -1;
  for (let i = 0; i < l2; i++) {
    if (l2 - i < l) return -1;
    for (let j = 0; j < l; j++) {
      if (haystack[i + j] !== needle[j]) break;
      if (j === l - 1) {
        return i;
      }
    }
  }
  return -1
};

3.搜索插入位置

题目:

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

思路:分两种情况,一是有相等的元素,二是没有相等的元素。

相等的情况很容易区分,不相等的时候,可以这样,因为原数组是排序号的,我们一直记录比目标值小的成员的下标即可,最后返回+1的值

  let l = nums.length,
    j = -1;
  for (let i = 0; i < l; i++) {
    if (nums[i] === target) return i;
    if (nums[i] < target) j = i;
  }
  return j+1;

优化方向:提前终止循环

  let l = nums.length,
    j = -1;
  if (target <= nums[0]) return 0;
  if (target > nums[l - 1]) return l;
  for (let i = 0; i < l; i++) {
    if (nums[i] === target) return i;
    if (nums[i] < target) j = i;
  }
  return j + 1;

优化方向:二分法查找,而非单次遍历,减少比较次数:

    let left = 0;
    let right = nums.length - 1;
    if (target > nums[right]){ return right + 1; }
    if(target<=nums[0])return 0
    while (left < right) {
        let index = (left + right) >>> 1;//取左中位数
        if (nums[index] < target){
            left = index + 1;
        }else{
            right = index;
        }
    }
    return left;

4.外观数列

题目:

「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221
1 被读作  "one 1"  ("一个一") , 即 11。
11 被读作 "two 1s" ("两个一"), 即 21。
21 被读作 "one 2",  "one 1" ("一个二" ,  "一个一") , 即 1211。

给定一个正整数 n(1 ≤ n ≤ 30),输出外观数列的第 n 项。

注意:整数序列中的每一项将表示为一个字符串。

思路:从左到右,双重循环,第一次循环是记录n的值,第二轮循环是遍历上一轮循环的结果,根据上一轮的结果得到这一轮的结果。所以首先需要一个变量保存上一轮的结果,一个变量计算这一轮的结果。

此外,还要有一个变量记录当前遇到的数是什么数,一个变量记录当前数出现的次数

遍历上一轮的结果,比较每一个字符串和当前字符串,如果相同,则变量+1,如果不同,则先对结果拼接,然后更新当前的数,

var countAndSay = function (n) {
  if (n == 1) return "1";
  let res = "1",
    v = "0",
    a = 0,
    r = "";
  for (let i = 1; i < n; i++) {
    let l = res.length;
    for (let j = 0; j < l; j++) {
      if (res[j] !== v) {
        if (a) {
          r += `${a}${v}`;
        }
        v = res[j];
        a = 1;
      } else {
        a++;
      }
    }
    if (a) {
      r += `${a}${v}`;
    }
    v = "0";
    res = r;
    a = 0;
    r = "";
  }
  return res;
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值