力扣算法刷题记录


前言

没刷过算法题,感觉自己算法方面的知识较为薄弱,在力扣上看了几道发现自己都不会,看了解题答案后才感觉逐渐明朗,所以来记录一下算法题。

一、数组篇

Day1

一、问题一

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

1.第一种解法

 function merge(nums1: number[], m: number, nums2: number[], n: number): void {
            //表示合并的nums1的最后一个索引值
            let k = m + n - 1;
            //nums1的最后一个索引值
            let i = m - 1;
            //nums2的最后一个索引值
            let j = n - 1;
            //当数组1和数组2的索引值都>=0时则可以进行循环
            while (i >= 0 && j >= 0) {
                //如果数组1的最后一个索引值对应的数值>数组2最后一个值对应的数值 则k所对应的最大值则变为i对应的值 反之则为索引j对应的值
                //进行一次操作后 索引值减小 x-- 是先赋值后进行运算
                nums1[k--] = nums1[i] > nums2[j] ? nums1[i--] : nums2[j--];
            }
            //如果存在数组2循环完之后 数组1的排序还没进行完成
            while ((j < 0 && i >= 0) ) {
                nums1[k--] = nums1[i--];
            }
            //如果存在数组1循环完之后 数组2的排序还没进行完成时
            while (i < 0 && j >= 0) {
                nums1[k--] = nums1[j--];
            }
        }

2.第二种解法

function merge(nums1: number[], m: number, nums2: number[], n: number): void {
            //splice方法 从索引开始 删除n个元素,再添加nums2数组内的元素
            nums1.splice(m, n, ...nums2);
            nums1.sort((a, b) => a - b);
        }

 二、问题二

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

注意:不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}
function removeElement(nums: number[], val: number): number {
    let count = 0
    //把每一次循环到不等于val的值依次赋值给索引从0开始
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] !== val) {
            nums[count] = nums[i]
            count++
        }
    }
    return count
};

 三、问题三

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

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

1.第一种解法

function removeDuplicates(nums: number[]): number {
    let count=0
    for (let i = 1; i < nums.length; i++) {
        //若值不一样则可以将nums[i]的值赋值给count+1所对应的值
        if (nums[count] !== nums[i]) {
            nums[++count] = nums[i]
        }
    }
    //输出长度 长度为索引值+1
    return ++count
};

 2.第二种解法

 function removeDuplicates(nums: number[]): number {
            for (let i = 1; i < nums.length; i++) {
                //前一个值等于后一个值
                if (nums[i - 1] === nums[i]) {
                    nums.splice(i, 1);
                    //删除后后面的元素变成当前索引值对应的值,则需要再次进行一次
                    i--;
                }
            }
            return nums.length;
        }

 四、问题四

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。

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

 第一种解法(与问题三方法类似)

function removeDuplicates(nums: number[]): number {
    for (let i = 1; i < nums.length; i++) {
        //因为一致的元素只能出现两次,所以如果连续三个值都相等则需要删除一个值
        if (nums[i - 1] === nums[i] && nums[i] === nums[i + 1]) {
            nums.splice(i, 1)
            i--
        }
    }
    return nums.length
};

第二种解法

function removeDuplicates(nums: number[]): number {
    let j = 0
    for (let i = 0; i < nums.length; i++) {
        //索引值为0,1时直接赋值/或者当索引值为x时不与前面x-2索引值相等则说明只会出现2次
        if (j < 2 || nums[i] !== nums[j - 2]) {
            //在这里已经增加了j,返回则不需要了
            nums[j++] = nums[i]
        }
    }
    return j

 Day2

一、问题一

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

 第一个解法:

自己琢磨的解法,题目理解没到位,题目已经说了数组总是存在多数元素,所以只需要找到出现次数最多的一个元素就行,而且多数元素只能出现一次,如果有两个那就是大于n,所以不成立

//题目意思是总是存在出现次数大于数组一半的值,所以只需要找到这个值就行
//这个方法相当于重复了一遍题目所说的n/2 比较繁琐的解法
function majorityElement(nums: number[]): any {
    const map = new Map()
    nums.forEach((item: any) => map.has(item) ? map.set(item, map.get(item) + 1) : map.set(item, 1))
    let n: any
//遍历键值对,key返回的是数组,第一个索引值为属性,第二个索引值为属性值
    for (let key of map) {
        if (key[1] > (nums.length / 2)) {
            n = key[0]
        }
    }
    return n

};

第二个解法(力扣学到的解法)

function majorityElement(nums: number[]): number {
    let n = 0
    let m = 0
    for (let num of nums) {
        if (n === 0) {
            m = num
        }
        //通过出现的次数来反复抵消,最多的那个则是出现次数最多的
        m === num ? ++n : --n
    }
    return m
};

二、问题二

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

 

//没有返回值直接修改传入的数组  //k为非负数
function rotate(nums: number[], k: number): void {
    const n = nums.length
    //将数组先赋给一个新数组
    let arr: any = [...nums]
    nums.forEach((item, index) => {
        //(移动的k个位置+索引)再除以数组的长度取余则为该值移动后的索引值
        nums[(k + index) % n] = arr[index]
    })
};
  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值