LeetCode第四周

180 阅读4分钟

删除数组中的重复项

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。

你不需要考虑数组中超出新长度后面的元素。

难易度:简单

解题思路

  1. 双指针

因为题目中的数组是有序数组,所以只要后一位和前一位不同,那么肯定后面不会有相同的数,那么就只需要把所有不重复的数,移动到数组前面就可以了。所以考虑使用双指针的方式,记录两个数字的位置,按位比较

var removeDuplicates = function (nums: number[]) {
   let pre = 0 // 无重复数组的最后一个位置
   let next = 1 // 下一个需要比较数字的指针
   const len = nums.length
   while(next < len){
       if (nums[pre] == nums[next]){ // 遇到两个数重复了
           next++ // 后移需要比较的指针
       } else {
           nums[pre + 1] = nums[next] // 当遇到不重复的数字时,将这个数前移
           pre++
           next++
       }
   }
   return pre + 1
};

实现 strStr() 函数。

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

示例 1:

输入: haystack = "hello", needle = "ll"

输出: 2

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

难易度:容易

解题思路:

  1. 利用indexof。indexof为内置函数,在内部是做了很多优化的,在任何时候自己写的函数,优化肯定是比不上内置函数的
var strStr = function(haystack: string, needle: string): number {
    return haystack.indexOf(needle)
};
  1. 找到needle在 haystack 中的位置,那么 就默认haystack是更长的字符串,遍历haystack,找到needle第0个字符串的位置,再截取一个和needle等长的字符串,进行比较
var strStr = function(haystack: string, needle: string): number {
    const nLen = needle.length
    if (!nLen) return 0

    const len = haystack.length

    for(let i = 0; i < len; i++){
        if (haystack[i] == needle[0]) {
            if (haystack.substring(i, i + nLen) == needle) return i
        }
    }
    return -1
};

两数相除

给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。

返回被除数 dividend 除以除数 divisor 得到的商。

整数除法的结果应当截去(truncate)其小数部分

例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2

示例 1:

输入: dividend = 10, divisor = 3

输出: 3

解释: 10/3 = truncate(3.33333..) = truncate(3) = 3

提示:

  • 被除数和除数均为 32 位有符号整数。
  • 除数不为 0。
  • 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−2^31,  2^31 − 1]。本题中,如果除法结果溢出,则返回 2^31 − 1。

难易度:中等

解题思路:

  1. 既然不能用乘法和除法,那么就用减法嘛,除法可以理解为 被除数 减去n次 除数,n为除法的整数解,但是这题有几个坑
  • 题中数字是32位有符号整数,但是Math.abs(-2^31)是会越界的,所以把所有的数都变成负数去计算
  • 特殊情况 -2^31 / -1 是会越界的(别问我怎么知道的)
var divide = function (dividend: number, divisor: number) {
    if (dividend <= -Math.pow(2, 31) && divisor == -1) return Math.pow(2, 31) -1 // 特殊情况
    const flag = (dividend < 0 && divisor < 0) || (dividend >= 0 && divisor >= 0) // 用于结果是正还是负
    dividend = -Math.abs(dividend)
    divisor = -Math.abs(divisor)

    let res = 0
    while (dividend <= divisor) { // 循环相减
        dividend = dividend - divisor
        res++
    }
    return flag ? res : -res
};
  1. 位运算符

dividend每次减去2^n个divisor(尽可能多),同时res每次加2^n

var divide2 = function (dividend: number, divisor: number) {
    if (dividend <= -Math.pow(2, 31) && divisor == -1) return Math.pow(2, 31) - 1

    const flag = (dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0);

    dividend = -Math.abs(dividend)
    divisor = -Math.abs(divisor)

    let res = 0
    while (dividend <= divisor) {
        let temp = divisor
        let cal = 1

        while (dividend - temp <= temp) {
            temp = temp << 1
            cal = cal << 1
        }
        dividend -= temp
        res += cal
    }
    return flag ? res : -res
};

唉,这周公司项目太忙了,同时又在学习python深度学习,高数那段搞得我头昏脑涨的,都没刷几道题,我太难了!