刷题日记01.20
数据结构
217. 存在重复元素 - 力扣(LeetCode) (leetcode-cn.com)
1. 解题思路
利用Set()以及has函数
新建一个空字典,遍历数组nums,若字典中没有这个数据,则加入字典;反之返回true;遍历未返回,则数组内无重复数据。
1. 代码
/**
* @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;
};
53. 最大子数组和 - 力扣(LeetCode) (leetcode-cn.com)
2.解题思路
动态规划
递归式的动态规划,找到问题中的“递归”条件。
寻找最大子数组和,变化量是数组长度,如果找以第i个元素为开头的最大子数组,那么你不知道最后添加元素与原来最大子数组和的位置关系,也就没有n和n+1的递归关系。而以第i个元素为结尾的最大子数组,那么新加入的元素要么接在n的最大子数组后,要么独立成组,进而n和n+1的递归关系出现
2.代码
var maxSubArray = function (nums) {
var len = nums.length;
var dp = [];
dp[0] = nums[0];
var out = dp[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];
}
out = out > dp[i] ? out : dp[i];
}
return out;
};
算法(二分查找)
704. 二分查找 - 力扣(LeetCode) (leetcode-cn.com)
1.解题思路
二分查找,提供两个标记,每次比较后数据量减半,左标记初始为0;右标记初始为length-1;
每次取两标记的中间mid的数组值nums[mid]与target比较,比中则返回下标;若小于,则右标记改为mid-1(mid已经比过了使小于target的);若大于,则左标记改为mid+1(mid已经比过了使大于target的)
1.代码
/**
* @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)
2.解题思路
找出第一个错误版本,对半查找
设置两个标记点,每次取中间的标记点mid进行比较:如果错误,则第一个错误版本为该点或该点左侧,所以右标记点改为mid;反之如果正确,则第一个错误版本为该点的右侧,所以左标记点改为mid+1;
2.代码
/**
* 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)
3.解题思路
依然设置两个标记点,每次比较两个标记点的中间值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即可;
3.代码
/**
* @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;
};