小花笔记
文章目录
前言
个人记录,仅做参考
一、两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。
var twoSum = function(nums, target) {
let map = new Map();
for(let i = 0; i< nums.length; i++){
if(map.has(target - nums[i])){
return [map.get(target - nums[i]), i];
}else{
map.set(nums[i], i);
}
}
return [];
};
思路:
1.定义一个map用来存储目标值及目标值的下标
2.遍历nums数组
3.判断map中是否存在目标值减去当前数字等于的数值,如果存在就返回当前数字的下标及另一个数字的下标;如果不存在就把当前数字及下标存到map中;
4.执行完遍历还是没有符合条件的数字就返回空数组
二、存在重复元素
给定一个整数数组,判断是否存在重复元素。
如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。
var containsDuplicate = function(nums) {
var map = new Map();
for(var i = 0 ; i < nums.length ; i++){
if(map.has(nums[i])){
return true;
}else{
map.set(nums[i])
}
}
return false;
};
思路:
1.定义一个map用来存储nums中的数值
2.遍历nums数组
3.判断map中是否存在这个数字,如果存在就返回true,如果不存在就把这个数存到map中;
4.执行完遍历还是没有符合条件的返回false
三、存在重复元素||
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。
输入: nums = [1,2,3,1], k = 3
输出: true
输入: nums = [1,2,3,1,2,3], k = 2
输出: false
var containsNearbyDuplicate = function(nums, k) {
var map = new Map();
for(var i = 0 ; i < nums.length ; i++){
if(map.has(nums[i])){
if(i -map.get(nums[i]) <= k){
return true;
}else{
map.set(nums[i],i);
}
}else{
map.set(nums[i],i);
}
}
return false;
};
思路:
1.定义一个map用来存储nums中的数字和数字下标
2.遍历nums数组
3.判断map中是否存在这个数字,如果存在就执行判断逻辑;如果不存在就把这个数字和它的下标存到map中;
4.如果存在的判断逻辑,当前遍历下标为i的数字和map中已经存在的数字下标的差,是否小于等于K,如果小于等于,则返回true;反之,更新map中已经存在数字的下标为当前最新下标值; nums = [1,0,1,1], k = 1
5.执行完遍历还是没有符合条件的返回false
四、快乐数
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 true ;不是,则返回 false 。
输入:19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
输入:n = 2
输出:false
提示:1 <= n <= 231 - 1
var isHappy = function(n) {
var flag = false;
var ar = []
var deal = function(n){
let arr = n.split('');
let sum = 0;
for(i in arr){
sum += Math.pow(arr[i],2);
}
if(sum == 1){
flag= true;
return false;
}else{
if(!ar.includes(sum)){
ar.push(sum)
deal(sum.toString())
}else{
flag = false;
return false;
}
}
}
deal(n.toString())
return flag;
};
思路:
1.定义一个ar 数组用来存储每个位置上的数字的平方和;定义一个函数deal 用来执行求和过程;
2.deal 函数中,将数字n分割成数组arr 对其进行遍历求和sum;判断sum是否等于1,如果等于返回true;如果不等于,判断ar数组中是否存在该数字(之前数字的各个位置上的数字平方和),如果不存在,将当前sum的数值存进去,调用deal函数进行求和计算;如果存在,说明这个n不是快乐数(因为各个位置求和的数字再次出现说明进入了循环,这个数的和永远不可能等于1),返回false。
五、合并两个有序数组
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
var merge = function(nums1, m, nums2, n) {
var p = m+n-1;
var p1 = m-1;
var p2 = n-1;
while(p2 >= 0){
if(p1 < 0){
nums1[p--] = nums2[p2--];
}else if(nums1[p1] < nums2[p2]){
nums1[p] = nums2[p2];
p2--;
p--;
}else{
nums1[p] = nums1[p1];
p1 --;
p--;
}
}
};
思路:
1.定义三个指针,p指向合并完成数据的最后一位,p1指向nums1的最后一位,p2指向nums2的最后一位
2.nums2合并到nums1中,那么当nums2中的元素全部移走即结束判断
3.p1小于0,说明nums1已经都比较完成,此时把nums2中的元素赋值过来;如果nums1[p1] < nums2[p2],将nums2[p2]赋值给nums1[p],p2和p指针都左移一位;反之,p1和p都左移一位
六、多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素
输入:[2,2,1,1,1,2,2]
输出:2
var majorityElement = function(nums) {
var number = nums[0],count=0;
for(i in nums){
if(nums[i] == number){
count++;
}else{
count--;
if(count == 0){
number = nums[i];
count++;
}
}
}
return number;
};
思路:
1.定义数字出现次数count=0,number=nums[0]假设出现次数最多的就是数字的第一位数字。
2.遍历nums数组,比较当前下标为i的数字是否等于number,如果相等count加一,如果不相等count减一
3.count再次等于0时,将最新nums[i]赋值给number,count加一。
4.遍历结束,最后返回number
七、搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4
var searchInsert = function(nums, target) {
var left=0,right = nums.length -1;
while(left <= right){
var middle = Math.floor((left+right)/2);
if(nums[middle] < target){
left = middle +1;
}else if(nums[middle] > target){
right = middle - 1;
}else{
return middle;
}
}
return left;
};
思路:
1.定义两个指针,一个指向数组头left,一个指向数组尾部right
2.如果left小于等于right则执行判断逻辑
3.定义指针middle,指向left 和right的中间位置;如果nums[middle]小于目标值,left移动到middle+1的位置上;如果nums[middle]大于目标值,right移动到middle-1的位置;如果三个指针重合则返回middle的位置;否则返回left;
八、整数反转
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)
示例 1:
输入:x = 123
输出:321
示例 2:
输入:x = -123
输出:-321
示例 3:
输入:x = 120
输出:21
示例 4:
输入:x = 0
输出:0
var reverse = function(x) {
let flag = '';
let str = x.toString();
if(str[0] === '-' || str[0] === '+'){
flag = str[0];
str = str.slice(1,str.length);
}
str = str.split('').reverse().join('');
let number = Number(flag+str);
if(number<=Math.pow(-2,31) || number >= Math.pow(2,31) -1){
return 0;
}
return number;
};
思路:
1.将数组转换成字符串
2.判断字符串是否包含符号,如果包含就将符号存储咋在flag字段中,截取费符号部分内容
3.将处理完的字符串经过一系列函数操作后,恢复成数字number
4.如果number不在有符号整数范围内就返回0,反之就返回number
九、回文数
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
示例 1:
输入:x = 121
输出:true
示例 2:
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。
示例 4:
输入:x = -101
输出:false
var isPalindrome = function(x) {
let reverseX = Number(x.toString().split('').reverse().join(''));
if(x === reverseX){
return true;
}else{
return false;
}
};
思路:
1.定义reverseX 存储数字翻转以后的值,比较x和reverseX是否相等,相等即返回true,反之就返回false。
十、罗马数组转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。
示例 1:
输入: “III”
输出: 3
示例 2:
输入: “IV”
输出: 4
示例 3:
输入: “IX”
输出: 9
示例 4:
输入: “LVIII”
输出: 58
解释: L = 50, V= 5, III = 3.
示例 5:
输入: “MCMXCIV”
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
var romanToInt = function(s) {
let obj = {
I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1000,
}
let sum = 0;
for(let i = 0 ; i < s.length ; i++){
if(obj[s[i]] < obj[s[i+1]]){
sum -= obj[s[i]];
}else{
sum += obj[s[i]];
}
}
return sum;
};
思路:
1.定义一个obj来存储罗马数字和数字之间的对应关系,定义sum存储要返回的整数
2.遍历字符串,如果左面的罗马数字对应的数值小于右面罗马数字对应的数值,sum就减去左面数字;反之,sum就加上左面的数值
3.最后返回罗马数字对应的整数
十一、删除有序数组中的重复项
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
var removeDuplicates = function(nums) {
if(nums.length ==0) return 0;
let i = 0;
for(let j = 1 ; j < nums.length ; j++){
if(nums[j] != nums[i]){
i ++;
nums[i] = nums[j];
}
}
return i+1;
};
var removeDuplicates = function(nums) {
for (var i = 0; i < nums.length;) {
if (nums.indexOf(nums[i]) !== i) {
nums.splice(i, 1);
} else {
i++;
};
};
return nums.length;
};
思路1:
1、初始化i=0,遍历数组从下标为1开始,比较nums[j] 和 nums[i]是否相等,如果相等返回的数组长度为i+1,不相等就让i右移一位,把当前nums[j]的值赋值给nums[i],继续进行比较直到相等返回数组长度i+1
思路2:
1、遍历数组,判断当前下标对应的数字是否是第一次在数组中出现的位置,如果是就让i右移一位,如果不是删除当前数值,直到遍历完成,返回数组的长度。
十一、冒泡排序
[10,20,9,8,79,65,100]
var sort = function (arr){
for(var i = 1 ; i < arr.length ; i++){
for (var j = 0 ; j < arr.length -i ; j++){
if(arr[j] > arr[j +1]){
var t = arr[j];
arr[j] = arr[j+1];
arr[j+1] = t;
}
}
}
return arr;
}
思路1:
1、比较两个相邻元素的大小,如果前一个比后一个大则交换位置
2、外层循环控制次数,内层循环遍历比较,因为每比较一轮,最后一个元素已经是当前最大的元素了,所以不用在进行比较
十二、快速排序
[10,20,9,8,79,65,100]
var quickSort = function (arr) {
if(arr.length <=1) return arr;
var pivot = arr.slice(0,1);
var leftArr = [],rightArr =[];
for(var i = 1 ; i < arr.length ; i++){
if(arr[i] < pivot){
leftArr.push(arr[i]);
}else{
rightArr.push(arr[i]);
}
}
return quickSort(leftArr).concat(pivot,quickSort(rightArr));
}
思路1:
1、快速排序是对冒泡排序的一种改进,第一趟排序时将数据分成两部分,一部分比另一部分的的所有数据都要小,然后进行递归调用,在两边都实行快速排序
十三、查找数组中出现次数最多元素
function searchMany(arr){
var map = new Map(),maxNum = 0,maxName;
for(let i = 0 ; i < arr.length; i++){
if(map.has(arr[i])){
map.set(arr[i],map.get(arr[i])+1)
if(map.get(arr[i]) > maxNum){
maxNum = map.get(arr[i]);
maxName = arr[i];
}
}else{
map.set(arr[i],1)
}
}
// for (var [key, value] of map) {
// if(value >maxNum){
// maxNum = value;
// maxName = key;
// }
// }
console.log('出现最多的元素:',maxName,'出现了几次',maxNum)
}
searchMany([1,3,2,3,5,3,5])
function searchMany(arr){
var map = new Map(),maxNum = 0,maxName;
for(let i of arr){
if(map.has(i)){
map.set(i,map.get(i)+1)
if(map.get(i) > maxNum){
maxNum = map.get(i);
maxName = i;
}
}else{
map.set(i,1)
}
}
console.log('出现最多的元素:',maxName,'出现了几次',maxNum)
}
searchMany([1,3,2,3,5,3,5])