刷题日记01.20

数据结构

217. 存在重复元素 - 力扣(LeetCode) (leetcode-cn.com)

解题思路

利用Set()以及has函数
新建一个空字典,遍历数组nums,若字典中没有这个数据,则加入字典;反之返回true;遍历未返回,则数组内无重复数据。

代码

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var containsDuplicate = function (nums) {
    var len = nums.length;
    var hash = new Set();  //新建字典
    for (let i = 0; i < len; i++) {
        if (hash.has(nums[i])) {   //has()函数,如果字典中有该数据则返回true;反之返回false
            return true;
        }
        hash.add(nums[i]);
    }
    return false;
};

Set()

  1. ES6 新的数据结构 成员的值唯一,无重复值

  2. 使用new Set()进行构造,add()方法向Set()结构加入成员

  3. 向Set()中加入值不会发生类型转换,所以1和”1“是不同的,但是NaN等于自身;且两个对象总是不相等。

  4. Set()结构的实例有以下属性。

    Set.prototype.constructor:构造函数,默认就是Set函数。
    
    Set.prototype.size:返回Set实例的成员总数。
    

    Set()实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于便利成员)。下面介绍四种操作方法。

    add(value):添加某个值,返回Set结构本身。
    delete(value):删除某个值,返回一个布尔值,标识删除是否成功
    has(value):返回一个布尔值,表示该值是否为Set成员。
    clear():清除所有成员,没有返回值。
    
  5. //将Set()转换为数组
    const items = new Set([1,2,3,4,5]);
    const array = Array.from(items);
    

53. 最大子数组和 - 力扣(LeetCode) (leetcode-cn.com)

解题思路

动态规划
寻找最大子数组和,变化量是数组长度,如果找以第i个元素为开头的最大子数组,那么你不知道最后添加元素与原来最大子数组和的位置关系,也就没有n和n+1的递归关系。而以第i个元素为结尾的最大子数组,那么新加入的元素要么接在n的最大子数组后,要么独立成组,进而n和n+1的递归关系出现

代码

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    var len=nums.length;
    var dp=[];
    dp[0]=nums[0];
    var out=nums[0];
    for(let i=1;i<len;i++){
        var sum=dp[i-1]+nums[i];
        if(sum>nums[i]){
            dp[i]=sum;
        }else{
            dp[i]=nums[i]
        }
        if(dp[i]>out){
            out=dp[i];
        }
    }
    return out;
};

动态规划

递归式的动态规划,找到问题中的“递归”条件。

算法(二分查找)

704. 二分查找 - 力扣(LeetCode) (leetcode-cn.com)

解题思路

二分查找,提供两个标记,每次比较后数据量减半,左标记初始为0;右标记初始为length-1;
每次取两标记的中间mid的数组值nums[mid]与target比较,比中则返回下标;若小于,则右标记改为mid-1(mid已经比过了使小于target的);若大于,则左标记改为mid+1(mid已经比过了使大于target的)

代码

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function (nums, target) {
    var left = 0;
    var right = nums.length - 1
    while (left <= right) {
        var mid = Math.floor((rigth-left)/2)+left;   //防止(left+right)溢出,JavaScript计算不会自动取整
        var num = nums[mid];
        if (num === target) {
            return mid;
        } else if (num > target) {
            right = mid - 1;
        } else if (num < target) {
            left = mid + 1;
        }
    }
    return -1;
};

278. 第一个错误的版本 - 力扣(LeetCode) (leetcode-cn.com)

解题思路

找出第一个错误版本,对半查找
设置两个标记点,每次取中间的标记点mid进行比较:如果错误,则第一个错误版本为该点或该点左侧,所以右标记点改为mid;反之如果正确,则第一个错误版本为该点的右侧,所以左标记点改为mid+1;

代码

/**
 * Definition for isBadVersion()
 * 
 * @param {integer} version number
 * @return {boolean} whether the version is bad
 * isBadVersion = function(version) {
 *     ...
 * };
 */

/**
 * @param {function} isBadVersion()
 * @return {function}
 */
var solution = function (isBadVersion) {
    /**
     * @param {integer} n Total versions
     * @return {integer} The first bad version
     */
    return function (n) {
        var low = 1, high = n;
        while (low < high) {
            var mid = Math.floor((high - low) / 2) + low;  //防止high+low溢出
            if (isBadVersion(mid)) {
                high = mid;
            } else {
                low = mid+1;  //左右标记点变化必须要有一个mid加减1,这样二分到最后才可以跳出循环
            }
        }
        return low;
    };
};

35. 搜索插入位置 - 力扣(LeetCode) (leetcode-cn.com)

解题思路

依然设置两个标记点,每次比较两个标记点的中间值nums[mid],如果nums[mid]>target,右标记点设为mid-1(≥left);反之,左标记点设为mid+1(≤right)。(若出现相等情况,直接返回mid即可)根据这样标记点的转换,易得最后跳出循环的状态一定是left与right相等,再比较一次,跳出循环。下面考虑left=right后的情况(此时的mid==right)
(1) 如果此时nums[mid]==target,直接返回mid即可,同上;
(2) 如果此时nums[mid]>target,那么target应该插在mid处,进而原nums[mid]变为nums[mid+1];并且此时right = mid - 1;
故函数返回right+1即可;
(3) 如果此时nums[mid]<target,那么target应该插在mid+1处,进而原nums[mid]仍为nums[mid];此时right不变
故函数返回right+1即可;

代码

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function (nums, target) {
    var left = 0, right = nums.length - 1;
    while (left <= right) {
        var mid = Math.floor((right - left) / 2) + left;
        var num = nums[mid];
        if (num == target) {
            return mid;
        } else if (num > target) {
            right = mid - 1;
        } else if (num < target) {
            left = mid + 1;
        }
    }
    return right+1;
};

二分查找

  1. 左右标记点至少存在一个mid±1,来跳出循环条件;
  2. JavaScript计算会保留小数,所以需要math.floor取整
  3. 使用Math.floor((rigth-left)/2)+left来代替Math.floor((left+right)/2),以防求和时溢出
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值