小花笔记之算法小记

小花笔记


前言

个人记录,仅做参考


一、两数之和

给定一个整数数组 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])
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值