leetcode之数论与模拟刷题总结1

leetcode之数论与模拟刷题总结1

1-回文数
题目链接:题目链接戳这里!!!

先来简单题练练手,哈哈

思路1:调库法

class Solution {
    public boolean isPalindrome(int x) {
        if(x<0){
            return false ;
        }
        String str1 = String.valueOf(x) ;
        StringBuilder str = new StringBuilder(str1) ;
        str.reverse() ;
        for(int i=0; i<str1.length(); i++){
            if(str.charAt(i) != str1.charAt(i)){
                return false ;
            }
        }
        return true ;
    }
}

在这里插入图片描述
思路2:双指针

class Solution {
    public boolean isPalindrome(int x) {
        if(x<0){
            return false ;
        }
       String s = String.valueOf(x) ;
       int low = 0, high = s.length()-1 ;
       while(low<=high){
           if(s.charAt(low)!=s.charAt(high)){
               return false ;
           }
           low ++ ;
           high -- ;
       }
       return true ;
    }
}

在这里插入图片描述
2-整数翻转
题目链接:题目链接戳这里!!!

思路1:模拟法,整数转换成字符串,从后先前遍历,做翻转处理,对返回的结果做异常处理,如果超过整数范围,捕获异常,并返回0。

class Solution {
    public int reverse(int x) {
        if(x>=-9 && x<=9){
            return x ;
        }
        String str = String.valueOf(x) ;
        boolean flag = true ;
        String s = "" ;
        for(int i=str.length()-1; i>=0; i--){
            if(str.charAt(i)=='-'){
                s  = str.charAt(i) + s ;
            }else if(str.charAt(i)=='0' && flag){
                continue ;
            }else{
             flag = false ;
            s += str.charAt(i) ;
            }
        }
        try{
        return Integer.parseInt(s) ;
        }catch(Exception e){
            return 0 ;
        }
    }
}

在这里插入图片描述
思路2:数学法

高效率,每次将x的最后一位加到n中,同时将x中的最后以为删除。

class Solution {
    public int reverse(int x) {
       long n = 0 ;
       while(x!=0){
           n = n*10 + x%10 ;
           x /= 10 ;
       }
       return (n>Integer.MAX_VALUE || n<Integer.MIN_VALUE) ? 0 : (int)n ;
    }
}

在这里插入图片描述
3-罗马数字转整数
题目链接:题目链接戳这里!!!

思路:模拟过程, 从后向前遍历罗马字符换,如果当前字符大于等于上一个字符,则累加当前字符对应的数字,反之累减当前字符对应的数字。

class Solution {
    public int romanToInt(String s) {
        int num1=0, num2 = 0, value = 0;
        for(int i=s.length()-1; i>=0; i--){
            switch(s.charAt(i)){
                case 'I' : num1 = 1 ; break ;
                case 'V' : num1 = 5 ; break ;
                case 'X' : num1 = 10 ; break ;
                case 'L' : num1 = 50; break ;
                case 'C' : num1 = 100; break ;
                case 'D' : num1 = 500; break ;
                case 'M' : num1 = 1000; break ;
            }
            if(num1>=num2){
                value += num1 ;
            }else{
                value -= num1 ;
            }
            num2 = num1 ;
        }
        return value ;
    }
}

在这里插入图片描述
4-整数转罗马数字
题目链接:题目链接戳这里!!!
思路:模拟法,从最大的找,找到最大的能表示的罗马数字,则将当前数字减去罗马数字对应得数字,依次将罗马数字添加到字符串后即可。

class Solution {
    public String intToRoman(int num) {
        String [] str = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"} ;
        int [] value = {1000,900,500,400,100,90,50,40,10,9,5,4,1} ;
        String res = "" ;

        for(int i=0; i<13; i++){
            while(num>=value[i]){
                num -= value[i] ;
                res += str[i] ;
            }
        }
        return res;

    }
}

在这里插入图片描述
5-逆波兰表达式求值
题目链接:题目链接戳这里!!!

思路:使用栈模拟后缀表达式转换成中缀表达式的过程即可。
如果当前的是数字,则进栈,如果当前的是运算符,则连续出栈两个元素,通过该运算符运算过后,再入栈,如此下去,最后栈中就一个元素,就是我们要求的值。

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<String> stack = new Stack<>() ;
        for(int i=0; i<tokens.length; i++){
            if(!tokens[i].equals("+") && !tokens[i].equals("-") && !tokens[i].equals("*") && !tokens[i].equals("/")){
         stack.push(tokens[i]) ;       
            }else{
                int a = Integer.parseInt(stack.pop()) ;
                int b = Integer.parseInt(stack.pop()) ;
                int res=0 ;
                switch(tokens[i]){
                    case "+" : res = b + a ; break ;
                    case "-" : res = b - a ; break ;
                    case "*" : res = b * a ; break ;
                    case "/" : res = b / a ; break ;
                }
                stack.push(String.valueOf(res)) ;
            }
        }
        return Integer.parseInt(stack.pop()) ;
    }
}

在这里插入图片描述
这样写起来看着更舒服

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>() ;
        for(int i=0; i<tokens.length; i++){
            if(!tokens[i].equals("+") && !tokens[i].equals("-") && !tokens[i].equals("*") && !tokens[i].equals("/")){
         stack.push(Integer.parseInt(tokens[i])) ;       
            }else{
                int a = stack.pop() ;
                int b = stack.pop() ;
                
                switch(tokens[i]){
                    case "+" : stack.push(b+a); break ;
                    case "-" : stack.push(b-a) ; break ;
                    case "*" : stack.push(b*a) ; break ;
                    case "/" : stack.push(b/a); break ;
                }
               
            }
        }
        return stack.pop() ;
    }
}

在这里插入图片描述
6-轮转数组
题目链接:题目链接戳这里!!!

思路:用栈来模拟数组轮转过程,每次轮转k%n次,若k%n为0,则不需要轮转.

class Solution {
    public void rotate(int[] nums, int k) {
        Stack<Integer> stack = new Stack<>() ;
        int n = nums.length ;
        for(int i=n-1; i>n-1-(k%n); i--){
            stack.push(nums[i]) ;
        }
        for(int i=n-1-(k%n); i>=0; i--){
            nums[i+(k%n)] = nums[i] ; 
        }
        for(int i=0; i<(k%n); i++){
            nums[i] = stack.pop() ;
        }
    }
}

在这里插入图片描述
7-矩形面积
题目链接:题目链接戳这里!!!

思路:主要就算判断两个矩形是否与交集,如果有,则两个矩阵面积和减去交集面积,若无交集,则直接求出两个矩阵的面积和。

class Solution {
    public int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) {
       int x1 = Math.max(ax1,bx1) ;
       int y1 = Math.max(ay1,by1) ;
       int x2 = Math.min(ax2,bx2) ;
       int y2 = Math.min(ay2,by2) ;

       if(x1>=x2 || y1>=y2){
           return (ax2-ax1) * (ay2-ay1) + (bx2-bx1) * (by2-by1) ; //无交集
       }else{
           return (ax2-ax1) * (ay2-ay1) + (bx2-bx1) * (by2-by1)- (x2-x1) * (y2-y1) ;//有交集
       }

    }
}

在这里插入图片描述
8-丑数
题目链接:题目链接戳这里!!!

思路:循环除以因子,判读最后是否等于1即可。

class Solution {
    public boolean isUgly(int n) {
        if(n<=0){
            return false ;
        }
  
        while(n%5==0 || n%3==0 || n%2==0){
            if(n%5==0){
                n /= 5 ;
            }else if(n%3==0){
                n /= 3 ;
            }else{
                n /= 2 ;
            }
        }
  
        return n == 1 ;
    }
}

在这里插入图片描述
写成递归形式也可以的。不过递归的效率不如循环。

class Solution {
    public boolean isUgly(int n) {
    if(n==1){
        return true ;
    }
    if(n==0){
        return false ;
    }
     if(n%5==0){
         return isUgly(n/5) ;
     }
     if(n%3==0){
         return isUgly(n/3) ;
     }
     if(n%2==0){
         return isUgly(n/2) ;
     }
     return false ;
    }
}

在这里插入图片描述
9-单调递增的数字
题目链接:题目链接戳这里!!!

思路:本题首先最容易想到的就是暴力解法,对每个数依次怕判断是否满足要求,这样的话对于数据量大的情况下会超时,这题比较好的做法是用贪心策略,局部最优,则全局最优。

题目要求小于等于N的最大单调递增的整数,那么拿一个两位的数字来举例。

例如:98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]–,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。

这一点如果想清楚了,这道题就好办了。

局部最优:遇到strNum[i - 1] > strNum[i]的情况,让strNum[i - 1]–,然后strNum[i]给为9,可以保证这两位变成最大单调递增整数。

全局最优:得到小于等于N的最大单调递增的整数。

但这里局部最优推出全局最优,还需要其他条件,即遍历顺序,和标记从哪一位开始统一改成9。

此时是从前向后遍历还是从后向前遍历呢?

从前向后遍历的话,遇到strNum[i - 1] > strNum[i]的情况,让strNum[i - 1]减一,但此时如果strNum[i - 1]减一了,可能又小于strNum[i - 2]。

这么说有点抽象,举个例子,数字:332,从前向后遍历的话,那么就把变成了329,此时2又小于了第一位的3了,真正的结果应该是299。

所以从前后向遍历会改变已经遍历过的结果!

那么从后向前遍历,就可以重复利用上次比较得出的结果了,从后向前遍历332的数值变化为:332 -> 329 -> 299

class Solution {
    public int monotoneIncreasingDigits(int n) {
      
     String str = String.valueOf(n) ;
     char [] c = str.toCharArray() ;
     int len = c.length ;
     for(int i=len-2; i>=0; i--){
         if(c[i]>c[i+1]){
             c[i] -- ;
         for(int j=i+1; j<len; j++){
             c[j] = '9' ;
         }
         }
     }
     return Integer.parseInt(String.valueOf(c)) ;
    }
}

在这里插入图片描述
10-消除游戏
题目链接:题目链接戳这里!!!

思路:模拟等差数列消除的过程,每一次正方向或者反方向消除后,数字的数量cnt/2,步长需要乘以2,用k标记正反方向。

class Solution {
    public int lastRemaining(int n) {
        //模拟等差数列
        int cnt = n ;
        int step = 1, remain=1, k=0 ;
        while(cnt>1){
            if(k%2==0){ //正反向
            remain = remain + step ;
            }else{//反方向
            remain = (cnt&1)==0 ? remain : remain + step ;
            }
            k++ ;
            step *= 2 ;
            cnt /= 2 ;
        }
        return remain ;
    }
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

nuist__NJUPT

给个鼓励吧,谢谢你

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

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

打赏作者

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

抵扣说明:

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

余额充值