LeetCode初级算法笔记

目录

一、数组

1.1删除排序数组中的重复项

1.2买卖股票最佳时机

1.3旋转数组

 1.4存在重复元素

1.5只出现一次的数字

1.6两个数组的交集

1.7加1

1.8移动0

1.10有效的数独

1.11旋转图像

一、数组

1.1删除排序数组中的重复项

题目描述:给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。将最终结果插入 nums 的前 k 个位置后返回 k 。不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/x2gy9m/

 分析

设定left = 0;从下标1开始逐个遍历nums中的各个数值,并判断该数值是否与前面的数值相等;相等时,直接跳过;不相等是,left++;再添加到nums[left] 当中.最后返回的是删除重复数字后数组的长度,即left+1

class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums.length == 0||nums == null){
            return  0;
        }
        //int count = 0;
        int left = 0;
        for(int i = 1;i<nums.length;i++){
            if(nums[left] != nums[i]){
                left++;//左指针右移
                nums[left] = nums[i];

            }
        }
        return left+1;
    }
}

1.2买卖股票最佳时机

题目描述:给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。返回 你能获得的 最大 利润 。

链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/x2zsx1/

 分析:后一天的股价减去前一天的股价,若为正数则添加到利润当中,若为负数则直接跳过

class Solution {
    public int maxProfit(int[] prices) {
        int profit = 0;
        for(int i = 1; i<prices.length;i++){
            if(prices[i]-prices[i-1] > 0){
                profit += prices[i]-prices[i-1];
            }
        }
        return profit;
    }
}

1.3旋转数组

题目描述:给你一个数组,将数组中的元素向右轮转 `k` 个位置,其中 `k` 是非负数。

 分析:写一个反转函数,即第一个反转到最后一个,倒数第一个反转到第一个,依次类推。再掉用该函数,先进行全部反转,然后再将反转后的前k个进行反转,最后将后面的n-k个数组进行反转即可。

class Solution {
    public void rotate(int[] nums, int k) {
        /*int hold = nums[0];
        int temp = 0;
        int index = 0;
        boolean isVisited[] = new boolean[nums.length];
        for(int i = 0;i < nums.length;i++){
            index = (index + k)%nums.length;
            if(isVisited[index]){
                index = (index + 1)%nums.length;//已经访问过了,直接从下一个元素开始
                hold = nums[index];
                i--;

            }else{
                //当前值保留到下一位置,保存之前把下一位置的值保存到temp;
                isVisited[index] = true;
                temp = nums[index];
                nums[index] = hold;
                hold = temp;

            }
        }*/
        k = k % nums.length;
        reverse(nums,0,nums.length-1);
        reverse(nums,0,k-1);
        reverse(nums,k,nums.length-1);
    }
        public void reverse(int[] nums,int begin,int end){
            while(begin < end){
                int temp = nums[begin];
                nums[begin++] = nums[end];
                nums[end--] = temp;
            }
        }
         
    
}

 1.4存在重复元素

题目描述:给你一个整数数组 `nums` 。如果任一值在数组中出现 至少两次,返回 `true` ;如果数组中每个元素互不相同,返回 `false` 。

分析: 使用set特性,集合中的元素不能有重复的。将数组中的元素添加到set集合当中,再比较原数组的长度与set集合的长度。

class Solution {
    public boolean containsDuplicate(int[] nums) {
        //存在HashSet当中,不允许有重复的值
        HashSet<Integer> temp = new HashSet<Integer>();
        for(int i = 0;i<nums.length;i++){
            temp.add(nums[i]);

        }
        //比较temp与nums的长度,如果相等则返回false,否则返回true
        if(temp.size() == nums.length){
            return false;
        }else{
            return true;
        }
    }
}

1.5只出现一次的数字

题目描述:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/x21ib6/

 分析

方法1:先对原数组进行排序处理,然后比较相邻两个元素。若相等即nums[i-1]==nums[i],则继续循环 i = i+2

不同则返回nums[i-1].

方法2:将数组中的元素保存到HashSet当中,并判断能否加入。如果加入不了,则说明之前存入过,该值为重复值将其移除。最后剩下的为只出现一次的数字。

class Solution {
    public int singleNumber(int[] nums) {
        //方法1:先进行排序,比较相邻的两个
        
        /*Arrays.sort(nums);
        int temp = nums[0];
        for(int i = 1; i<nums.length;i = i+2){
            if(nums[i-1] != nums[i]){
                temp = nums[i-1];
                break;
            }
        }
        return temp;*/
        //保存到HashSet当中,如果加入不了则说明之前存入过是重复值将其移除。
        //最后剩余的为只出现一次的数字。
        HashSet<Integer> set = new HashSet<Integer>();
        for(int num : nums){
            //如果加入不了,说明之前已经保存进去了,为重复值,移除
            if(!set.add(num)){
                set.remove(num);
            }
        }
        return (int)set.toArray()[0];

    }
}

1.6两个数组的交集

题目描述:给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

链接:力扣

 分析:先对两个数组进行排序,分别使用两个指针指向数组开始的位置。如果两个指针指向的值相同,则为他们的交集,将该值加入到list集合当中,然后两个指针都向后移一个。如果指针指向的值不同,则指向的值小的指针后移,然后进行比较,直到其中一个指针移动到了末尾则结束。最后返回list集合。

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        List<Integer> list = new ArrayList<>();
        int i = 0;//指针1
        int j = 0;//指针2
        while(i<nums1.length && j<nums2.length){
            //两个指针指向的值相等
            if(nums1[i] == nums2[j]){
                list.add(nums1[i]);
                i++;
                j++;
            }else if(nums1[i] < nums2[j]){
                //两个指针指向的不相等时
                i++;
            }else {
                j++;
            }
        }
        int index = 0;
        int[] res = new int[list.size()];
        for(int k = 0;k < list.size();k++){
            res[index++] = list.get(k);
        }
        return res;

    }
}

1.7加1

题目描述:给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/x2cv1c/

分析:从数组的末尾不为9,直接加1

特殊情况:末尾为9时,加1之后变为0,前一位再加1,在进行判断。

class Solution {
    public int[] plusOne(int[] digits) {
        for(int i = digits.length -1;i>=0;i--){
            if(digits[i] != 9){
                digits[i] += 1;//元素不为9,直接加1返回
                return digits;
            }else{
                digits[i] = 0;//元素为9,需要置为0
            }
        }
        //能够到达这里,说明数组中所有的元素均为9.例如999,则需返回1000
        int[] temp = new int[digits.length+1];
        temp[0] = 1;
        return temp;
    }
}

1.8移动0

题目描述:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。

 分析:从头开始遍历,非0的数值往前挪。

class Solution {
    public void moveZeroes(int[] nums) {
        int index = 0;
        for(int i = 0;i<nums.length;i++){
            //非零数字往前挪
            if(nums[i] != 0){
                nums[index++] = nums[i];
            }
        }
        //非零数字挪完之后,后面全部置为0
        while(index < nums.length){
            nums[index++] = 0;
        }
    }
}

1.9两数之和

题目描述:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。 链接:力扣

分析:设定两个指针,第一个指针从0开始,第二个指针从第一个指针的下一个进行遍历;寻找出两个指针对应数值相加等于target

将两个指针存入到res数组当中,返回res即可。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res = new int[2];
        for(int i = 0;i<nums.length;i++){
            for(int j = i+1;j<nums.length;j++){
                if(nums[i] + nums[j] == target){
                    res[0] = i;
                    res[1] = j;
                }
            }
        }
        return res;
    }
}

1.10有效的数独

题目描述:请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

注意:

一个有效的数独(部分已被填充)不一定是可解的。 只需要根据以上规则,验证已经填入的数字是否有效即可。 空白格用 '.' 表示。

链接:力扣

分析:判断数独是否有效,只需要判断同一行、同一列以及同一个3*3的小宫格内部不能存在相同的数值

创建3个9*9的布尔类型数组,分别表示行、列和3x3的小宫格。判断其内部是否存在重复的数字,如果存在直接返回false。

class Solution {
    public boolean isValidSudoku(char[][] board) {
        boolean[][] line = new boolean[9][9];//标记行
        boolean[][] colum = new boolean[9][9];//标记列
        boolean[][] cell = new boolean[9][9];//标记3*3的小宫格
        for(int i = 0;i<board.length;i++){
            for(int j = 0;j<board[0].length;j++){
                //不为数字,直接跳过
                if(board[i][j] == '.'){
                    continue;
                }
                int num = board[i][j]-'0'-1;//对应的数值
                int k = i/3*3+j/3;//表示第几个小宫格
                //判断当前行、列和小宫格是否有相同的数值
                if(line[i][num] || colum[j][num] || cell[k][num]){
                    return false;
                }
                line[i][num] = true;
                colum[j][num] = true;
                cell[k][num] = true;
           }
        }
        return true;

    } 
}

1.11旋转图像

题目描述:给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 链接:力扣

 分析:先进行上下对调,即第一行与最后一行进行对调;倒数第二行与第二行进行对调,以此类推。再进行对角线对调。

class Solution {
    public void rotate(int[][] matrix) {
        
        //先将第一行和最后一行进行对调,上下对调
        for(int i = 0;i<matrix.length/2;i++){
            int temp[] = matrix[i];
            matrix[i] = matrix[matrix.length-1-i];
            matrix[matrix.length-1-i] = temp;
        }
        //再进行对角线对调
        for(int i = 0;i<matrix.length;i++){
            for(int j = i+1;j<matrix[0].length;j++){
                int num = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = num;
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何必,去在意

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值