LeetCode一周学习(20220321-20220327)

​​​​​​#806 写字符串需要的行数

先用toCharArray()分割字符串,记录每个字符占的宽度,如果>100,则行数+1,换行,第二行为上一行最后加大于100的那个字符。依次往下遍历代码如下:

class Solution {
    public int[] numberOfLines(int[] widths, String s) {
        int[]ans=new int[2];//数组ans[0]表示行数 ans[1]表示每行的宽度
        ans[0]=1;
        for(char c:s.toCharArray()){
            int w=widths[c-'a'];
            ans[1]+=w;
            if(ans[1]>100){//如果大于100(一行宽度上限为100)
                ans[0]++;
                ans[1]=w;//最后一个字符无法写在上一行只能记载到下一行
            }
        }
        return ans;

    }
}

#27 移除元素
双指针解决,一个指针pos1遍历数组,另一个指针pos2=0指向数组初始位置,如果nums[pos1]!=val 则把pos1的值移到pos2,同时pos2往后。这样就可移除指定val元素。代码如下:

class Solution {
    public int removeElement(int[] nums, int val) {
        if(nums==null||nums.length==0) return 0;//如果数组为空或0直接返回0
        int j=0;//指向初始位置
        for(int i=0;i<nums.length;i++){//遍历数组
            if(nums[i]!=val){
                nums[j]=nums[i];
                j++;
            }
        }
        return j;

    }
}

#2125 银行中的激光束数量

思路简单明了:乘法原理进行相加,如果一行有激光器,则和上一行有激光器数量相乘,同时这一行激光器数量=pre,继续往下遍历。代码如下:

class Solution {
    public int numberOfBeams(String[] bank) {
        int n=bank.length;
        int []count=new int[n];//记每一行激光器的数量
        for(int i=0;i<n;i++){
            String arr=bank[i];
            for(int j=0;j<arr.length();j++){
                if(arr.charAt(j)=='1') count[i]++;
            }
        }
        int ans=0,pre=0;
        for(int i=0;i<n;i++){
          if(count[i]>0){//这一行有激光器
                ans+=pre*count[i];//上一行激光器数量乘这一行的数量就是产生激光束的数量
                pre=count[i];//往下继续
            }    
        }
        return ans;

    }
}

#2154 将找到的值乘以 2

思路1:用一个集合把数组值放入,如果数组中有需要找的值,则*2(一直到没有为止)输出

class Solution {
    public int findFinalValue(int[] nums, int original) {
        Set<Integer>set=new HashSet();//创建集合
        for(int i=0;i<nums.length;i++){
            set.add(nums[i]);//集合中加入值
        }
        while(set.contains(original)){//如果有original值
            original*=2;
        }
        return original;

    }
}

思路2:整体排序,然后从左到右遍历,如果有需要找的值,则*2

class Solution {
    public int findFinalValue(int[] nums, int original) {
        int n = nums.length;
        Arrays.sort(nums);
        for (int i = 0;i< n;i++){
            if (original == nums[i]){
                original *=2;
            }
        }
        
        return original;
    }
}
#2170 使数组变成交替数组的最少操作数

交替数组,即偶数项的位置都是同一个数,奇数项的位置也为同一个数,并且奇数项数值不等于偶数项数值,思路很简单:首先用两个哈希表,一个哈希表统计偶数项出现的数字和次数,一个哈希表统计奇数项出现的数字和次数,用一个二维数组记录最大数字和它的数字int[2][2]max,如果奇数最大的数字和偶数最大的数字不等,则最小操作数为数组长度-偶数最大数字次数-奇数最大数字次数。如果奇数最大数字和偶数最大数字相等,则最小操作数为数组长度-Max(奇数最大数字次数+偶数第二大数字次数,偶数最大数字次数+奇数第二大数字次数)代码如下:

class Solution {
    public int minimumOperations(int[] nums) {
        HashMap<Integer,Integer>even=new HashMap<Integer,Integer>();//偶数表
        HashMap<Integer,Integer>odd=new HashMap<Integer,Integer>();//奇数表
        int ans=0;
        for(int i=0;i<nums.length;i++){
            if(i%2==0) even.put(nums[i],even.getOrDefault(nums[i],0)+1);
            else odd.put(nums[i],odd.getOrDefault(nums[i],0)+1);
        }
        int[][]evenMaxAndSubMax=check(even);
        int[][]oddMaxAndSubMax=check(odd);
        if(evenMaxAndSubMax[0][0]!=oddMaxAndSubMax[0][0]) ans=nums.length-evenMaxAndSubMax[0][1]-oddMaxAndSubMax[0][1];
        else ans=nums.length-Math.max(evenMaxAndSubMax[0][1]+oddMaxAndSubMax[1][1],oddMaxAndSubMax[0][1]+evenMaxAndSubMax[1][1]);
        return ans; 
        
    }
    int[][]check(HashMap<Integer,Integer>map){//找位置最多数字和次多数字
        int[][]maxAndSubMax=new int[2][2];
        for(Integer key:map.keySet()){
            int val=map.get(key);
            if(val>maxAndSubMax[0][1]){
                maxAndSubMax[1][0]=maxAndSubMax[0][0];//次大数字
                maxAndSubMax[1][1]=maxAndSubMax[0][1];//次大数字次数
                maxAndSubMax[0][0]=key;
                maxAndSubMax[0][1]=val;
            }else if(val>maxAndSubMax[1][1]){
                maxAndSubMax[1][0]=key;
                maxAndSubMax[1][1]=val;
            }
        }
        return maxAndSubMax;
        
    }
}
#628 三个数的最大乘积

找整形数组中任意三数的最大乘积,有正有负,但是最大值肯定是Max(最大值*第二大值*第三大值,最小值*第二小值*最大值)这样就简单起来了

class Solution {
    public int maximumProduct(int[] nums) {
        int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
        int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE;

        for (int x : nums) {
            if (x < min1) {
                min2 = min1;
                min1 = x;
            } else if (x < min2) {
                min2 = x;
            }

            if (x > max1) {
                max3 = max2;
                max2 = max1;
                max1 = x;
            } else if (x > max2) {
                max3 = max2;
                max2 = x;
            } else if (x > max3) {
                max3 = x;
            }
        }

        return Math.max(min1 * min2 * max1, max1 * max2 * max3);
    }
}
#414 第三大的数

不管数字有多少个,只看数字的值的大小去找第三大的数,用a==null、b==null、c==null一次遍历来填充,如果c最后==null 返回a否则返回c

class Solution {
    public int thirdMax(int[] nums) {
        Integer a = null, b = null, c = null;
        for (int num : nums) {
            if (a == null || num > a) {
                c = b;
                b = a;
                a = num;
            } else if (a > num && (b == null || num > b)) {
                c = b;
                b = num;
            } else if (b != null && b > num && (c == null || num > c)) {
                c = num;
            }
        }
        return c == null ? a : c;
    }
}
#154 寻找旋转排序数组中的最小值 II

原本数组是升序的,进行了多次旋转,我们要找到最小值,如果最小值在中间,那么整体趋势肯定是先升后降再升的(可能中间会有相等的就会一条横线,但总体是前边的),所以遍历数组,设最小值为min=nums[0],从前往后遍历,只要nums[i+1]<=nums[i],那么min=Math.min(min,nums[i+1])

class Solution {
    public int findMin(int[] nums) {
        int min=nums[0],len=nums.length;
        for(int i=1;i<len;i++){
            if(nums[i]<=nums[i-1]) min=Math.min(nums[i],min);
        }
        return min;

    }
}

感觉二分法寻找更快,如果pivot=low+(high-low)/2,如果nums[pivot]<nums[high],证明最小值在左边,high=pivot,如果nums[pivot]>nums[high],证明最小值在右边,low=pivot+1,如果nums[pivot]==nums[high],high--往左移减少范围

class Solution {
    public int findMin(int[] nums) {
        int low = 0;
        int high = nums.length - 1;
        while (low < high) {
            int pivot = low + (high - low) / 2;
            if (nums[pivot] < nums[high]) {
                high = pivot;
            } else if (nums[pivot] > nums[high]) {
                low = pivot + 1;
            } else {
                high -= 1;
            }
        }
        return nums[low];
    }
}

写在最后的一点话:

原本是打算把这一周所有刷的题都写一个思路题解的,但本周开始的几天刷的都是随机一题,没有什么内在联系可言,同时几十题让我发现根本写不完题解o(╥﹏╥)o,在今天也让我下定决心,以后每天刷的题都会当天反思汇总起来,在每周末下午发出,一来让自己感觉到有点成就,二来也希望能帮助到别人。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值