力扣刷题手册

前言: 随缘刷题,认真记录

文章目录

      • 字符串相加
      • K次操作转字符串
      • 找出数组游戏的赢家
      • 粉刷天花板
      • 整理字符串

字符串相加

8/3力扣415字符串相加.

用字符串的方法来模拟加法过程,使用双指针从尾部开始遍历,逐个相加:
需要解决的问题:

  1. 进位。
  2. 两数长短不一致。

解决方案:
进位问题: 用一个变量记录每次相加中有没有进位,如果进位了该位置1,将加到下一个两两相加的结果中。
两数长度不一样: 有一个数已经到达数组头部时(已经加完了) 将其设为0,依然相加。

class Solution {
       
    public String addStrings(String num1, String num2) {
     
        StringBuffer res =new StringBuffer() ;
        char[] arr1=num1.toCharArray();
        char[] arr2=num2.toCharArray();

        int i=arr1.length-1,j=arr2.length-1,tmp=0,sum=0; 

        while(i>=0 || j>=0 || sum!=0 ) {
      
            int b =( (j<0)?0:arr2[j]-'0') ;
            int a= ( (i<0)?0:arr1[i]-'0'); 
            tmp=a+b+sum; 
            sum=tmp/10; 
            res.append(tmp%10) ;
            i--; j--; 
        }
        
        res.reverse() ;
        return res.toString();
    }
}

变量解析:
sum标志有没有进位,可以发现在while的条件判断中也加入了sum!=0的判断。

如果"9"和"1"相加,虽然两者长度相同,sum不为0时,依然需要多循环一次,完成下一位进一的动作。

tmp需要加入结果集,需要保证它只能是一位,%10可以保证其个位

做题感想:
巧妙使用变量表达每一次循环的状态,避免了经常使用if判断的冗余。学习把!
以前也有做过模拟大数相加的题,是以链表数据结构为载体的,当时没做出来,还是超出了范围,挖个坑,日后补上。

最后:
题目中提到了BigInteger这个类,随便了解一下:
java.math.BigInteger
java.math.BigInteger用来表示任意大小的整数(通常是超出long型的)。BigInteger内部用一个int[]数组来模拟一个整数。

两个BigInteger的运算或一个基本运算都需要使用方法。

它的构造函数有:
BigInteger(byte[] val)
BigInteger(String val)
BinInteger(String val, int radix) 等等

一些方法
BigInteger abs() 返回大整数的绝对值
BigInteger add(BigInteger val) 返回两个(this和val) 大整数的绝对值
BigInteger and(BigInteger val) : 返回两个大整数的按位与的结果

8.10更新 :

前言: 昨天写了2道题,记录了3种解法,结果在最后的时刻直接关了电脑,啥都没了。。 还能怎样,重写吧。。 以后决定写一题更新一次/(ㄒoㄒ)/~~

K次操作转字符串

K次操作转变字符串
力扣刷题手册_第1张图片

解题思路

  1. 这道题目就是要做一件事: 用一定的规则将一个字符替换成字母表中的另一个字母。
  2. i次操作,可以将 一个字母ch变换成 字母表ch+i位置上的字母。 计算出s和t同一位置上的字符相差的距离distance,和k的大小作比较即可。
  3. 要注意的是: 从a换到b, 可以替换1次,27次,52次… 可以找到它的规律: distance+26*(freq-1) : distance就是a到b的距离。 freq, 也就是相同距离的一对字母的出现的频率
class Solution {
     
    public boolean canConvertString(String s, String t, int k) {
     
        if(s.length()!=t.length())return false;
        int []cnt=new int[26];
        
        char str[]=s.toCharrArray();
        char tr []=t.toCharrArray();
        int distance;
        
        for(int i=0;i<str.length;i++){
     
            distance=t[i]-s.[i];
            if(distance<0)distance+=26;
            cnt[distance]++;
        }
        
        int max =0;
        int idx=0;
        for(int i=1;i<cnt.length;i++){
     
            if(cnt[i]>=max ){
     
                max=cnt[i];
                idx=i;
            }
        }
        return 26*(max-1)+idx<=k;  //将出现相同距离的最大频率和k相比。 
    }
}

数组 cnt[distance]=freq

找出数组游戏的赢家

8/12 力扣1535.
力扣刷题手册_第2张图片

  • 这道题一个迷惑说明是 “较小的整数移至数组的末尾”,可以试想如果每次输掉一个数字就要将它移到最后一个位置代价有多大,直接硬模拟是不可能的

  • 思路: 不需要直接移到最后,只需要维护两个指针,一直指向当前的要比较的两个数就可以了。

想到这里,就好办了,(我还想了一下,有没有可能在之前被丢弃的数字,会变成最后的赢家呢? 答案应该是不可能的。)

//我的ac代码。 
class Solution {
     
    public int getWinner(int[] arr, int k) {
     
        int zero=0, one=1 , count =0 ,winner = 0 ,len=arr.length ;
        while(one<len&&count<k){
     
            if(arr[zero]>arr[one]) {
     
                one++ ;
                count++ ;
                winner = arr[zero] ;
            }else{
     
                winner =arr[one] ;
                zero=one++; 
                count=1 ;
            }
        }
        return winner;
    }
}
//最后的赢家在k>1的情况下都是处于0的位置上的,所以,如果当前一轮比较是0号赢了,将count++, 如果是1号赢了,将重置count为1。 



//在题解上看到一些优秀的题解,在此搬运学习下
class Solution {
     
    public int getWinner(int[] arr, int k) {
     
        int win=arr[0],count=0;/*win:胜利者,count:获胜场次*/
        for(int i=1;i<arr.length&&count<k;i++){
     /*到达获胜场次跳出循环*/
            if(arr[i]<win){
     /*arr[i]比win小*的情况*/
                count++;
            }else{
     /*如果win输掉了产生新的胜利者,count置为1*/
                win=arr[i];
                count=1;
            }
        }
        return win;/*返回win*/
    }
}

作者:zhttty-2
链接:https://leetcode-cn.com/problems/find-the-winner-of-an-array-game/solution/zhi-xing-yong-shi-1-ms-zai-suo-you-java-ti-jia-278/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

粉刷天花板

8/12 领扣281.
题目本身不难,但是如果硬肝,会导致超时,就像我随便乱写的代码,就超时了,也想不到怎么优化。 还是参考了题解:
用了双指针,觉得有点不明觉厉(不明白为什么我的就超时了)

public long painttheCeiling(int s0, int n, int k, int b, int m, long a) {
     
         long  arr[] = new long  [n] ;
        arr[0]=s0;
        long count=0; 
        for(int i=1 ;i<n ;i++){
     
            arr[i] =(k*arr[i-1]+b)%m +1 + arr[i-1] ;
        }//计算得到的数组本身递增。 
        int right=arr.length-1;
        for(int i=0;i<n;i++){
     
        //Ac代码和我的超时版本差异就是这个for循环的里层
            while(right>=0&&arr[right]*arr[i]>a) {
     
                right-- ;
            }
            count+=(right+1) ;
        }
        return count ;
    }

指针right从最大的乘以最小的,并记录不符合题意的个数,当while循环结束后,right+1就是当前i位置上符合题意的个数。

整理字符串

8/14 力扣1544.

力扣刷题手册_第3张图片

解题思路(一)
直接在原字符串的基础上删除掉相邻一对字母。

要注意的是如果为"DABbaCcd"删掉Bb后会让Aa也成为符合条件的一对。除此之外,这道题就没有其他难点了。

为了防止漏删,一种解决方式是一旦删掉一对字母,就回到字符串的开头,重新遍历一次。

class Solution {
     
    public String makeGood(String s) {
     
        if(s.equals("") ||s.length()<2||s==null) return s; 
        StringBuffer  ans= new StringBuffer(s); 
        for(int i=0;i<ans.length()-1 ;) {
     
            if( Math.abs(ans.charAt(i)-ans.charAt(i+1)) == 32) {
     
                ans.delete(i,i+2) ; 
                i=0; 
            }
            else 
                i++ ; 
        }
        return ans.toString() ; 
    }
}

在评论区还能看到一些有意思的解法,本质上都是检查本次 “make good” 有没有更新的,如果有更新,就说明需要再check一次了。

解题思路二: 利用栈
将字符串一一放入栈中,当栈的长度大于等于2的时候,就开始检查栈顶两个元素是否符合条件,如果符合,就移除。

class Solution {
     
    public String makeGood(String s) {
     
        if(s.equals("") ||s.length()<2||s==null) return s; 

        StringBuffer  stack= new StringBuffer(); 
        
        for(int i=0;i<s.length();i++){
     
            stack.append(s.charAt(i)) ;
            int len = stack.length() ;
           
            if(len>=2 && Math.abs(stack.charAt(len-1)-stack.charAt(len-2) )==32 )
                stack.delete(len-2,len) ; 
        }
        return stack.toString() ; 
    }
}

你可能感兴趣的:(java,数据结构,leetcode)