[leetCode] 简单算法 (一)

107 阅读4分钟

1、两数之各

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 

 示例: 

 给定 nums = [2, 7, 11, 15], target = 9 ;

因为 nums[0] + nums[1] = 2 + 7 = 9 ;

所以回 [0, 1]

第一种解法:最直观,好理解,执行时间长

function twoSum(nums: string[], target: number) {
    const len = nums.length;
    let i = 0;
    while(i < len) {
        let j = 0;
        while(j < len) {
            if (i === j) {
                 j ++;
                continue;
            }
            if (nums[i] + nums[j] === target) {
                return [i, j]
            }
            j ++;
        }
        i ++;
    }
}

 第二种解法:更简洁,执行时间短

function twoSum(nums: string[], target: number) {
    const len = nums.length;
    const temp = {};
    let i = 0;
    while (i < len) {
        const other = target - nums[i];
        if (temp[other] !== undefined) {
            return [temp[other], i];    
        };
        // 将数组转成对象,数组的值为属性,下标为值;[2] => {2: 1}
        temp[nums[i]] = i;
        i ++;
    }
}

 2、整数反转

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 

 示例 1: 输入: 123 输出: 321 

 示例 2: 输入: -123 输出: -321 

示例 3: 输入: 120 输出: 21 

注意: 假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0

第一种解法:最直接,易想到

function reverse(x: number): number {    
    const str = x + '';
    if (str[0] === '-') {
        const num = -str.slice(1).split('').reverse().join('')
        return num < -(2**31 - 1) ? 0 : num;
    } else {
        const num = +str.split('').reverse().join('')
        return num > 2**31 ? 0 : num;
    }};

第二种解决: 简洁

function reverse(x: number): number {
    let fh = "", re;
   if(x<0){
        fh = "-";
        x = 0 - x;
    }
    re = +(x+"").split("").reverse().join("");
    if(re > (x<0?2**31:(2**31-1))){
        return 0;
    }else{
        return +(fh + re);
    }};

3、加一

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。  

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

 你可以假设除了整数 0 之外,这个整数不会以零开头。 

 示例 1: 

 输入: [1,2,3] 

输出: [1,2,4] 

解释: 输入数组表示数字 123

var plusOne = function(digits) {
    for(let i = digits.length - 1;i >= 0;i--){
        digits[i]++;
        digits[i] = digits[i]%10;
        if(digits[i] != 0) return digits;
    }
    digits.unshift(1);
    return digits
};

4、有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。 

有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。 

 示例 1: 输入: "()" 输出: true 

示例 2: 输入: "()[]{}" 输出: true  

示例3: 输入: "(]" 输出: false 

示例 4: 输入: "([)]" 输出: false 

示例 5: 输入: "{[][]}" 输出: true

解法:规律和栈的基本特点是一个样,先进后出;可以用push和pop模拟

function isValid(s: string): boolean {
    const map = new Map([['(',')'], ['[',']'],['{','}']]);
    const arr = s.split('');
    const stack = [];
    for(let i = 0; i < arr.length; i ++ ) {
        const item = arr[i]
        if (['(','[','{'].indexOf(item) > -1) {
            stack.push(item)
       } else {
            const temp = stack.pop();
            if (item !== map.get(temp)) {
                return false;
            }
        }
    }
    if (stack.length !== 0) {return false}
    return true;
};

5、删除排序数组中的重复项

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

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

示例 1: 给定数组 nums = [1,1,2], 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 你不需要考虑数组中超出新长度后面的元素。 

示例 2: 给定 nums = [0,0,1,1,1,2,2,3,3,4], 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 你不需要考虑数组中超出新长度后面的元素。

function removeDuplicates(nums: number[]): number {
    let b = 0;
    const len = nums.length;
    for(let i = 0; i < len; i++) {
        if(nums[i] !== nums[i + 1]) {
            nums[b] = nums[i];
            b ++
        }
            }
    return b
};

6、合并两个有序数组

给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。

 说明:  

初始化 nums1 和 nums2 的元素数量分别为 m 和 n。 

你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。 示例: 

 输入:

 nums1 = [1,2,3,0,0,0], m = 3 

 nums2  = [2,5,6], n = 3 

 输出: [1,2,2,3,5,6]  

第一解:暴力解,一个个比较再合并

function merge(nums1: number[], m: number, nums2: number[], n: number) {    let isDo = true;    let arr = [];    let i = 0;    let j = 0;    const temp_nums1 = nums1.slice(0, m)    const temp_nums2 = nums2.slice(0, n)    while(isDo) {        if (i < m && j <n) {            if (temp_nums1[i] < temp_nums2[j]) {                arr.push(temp_nums1[i])                i ++;            } else {                arr.push(temp_nums2[j]);                j ++            }        } else {            isDo = false;        }    }   const  result =  [...arr, ...temp_nums1.slice(i), ...temp_nums2.slice(j)]    result.forEach((val, ind) => {        nums1[ind] = val;    })};