Leetcode-Math題型

Leetcode 7. Reverse Integer 【Easy】
難點(diǎn)在于 int 越界問題,用int temp暫時代替即可.

class Solution {
    public int reverse(int x) {
        int res = 0;
        while(x != 0){
            int a = x % 10;
            int temp = res * 10 + a;    //處理越界問題
            if((temp-a)/10 != res) return 0;
            res = temp;
            x = x/10;
        }
        return res;
    }
}

Leetcode 165. Compare Version Numbers.【Medium】
http://www.runoob.com/java/java-regular-expressions.html
java正則表達(dá)式中吭练,. 匹配除"\r\n"之外的任何單個字符析显。\. 表示匹配 . 本身。為什么是兩個 \ 呢?java的 \ 等同于其他語言的一個 \ 浑侥。
難點(diǎn)在于Math.max() , 和 i<v1.length 的判斷。

class Solution {
    public int compareVersion(String version1, String version2) {
        String[] v1 = version1.split("\\.");
        String[] v2 = version2.split("\\.");
        for(int i=0; i<Math.max(v1.length,v2.length);i++){
            int num1 = i<v1.length? Integer.valueOf(v1[i]) : 0;
            int num2 = i<v2.length? Integer.valueOf(v2[i]) : 0;
            if( num1 > num2 ) return 1;
            if( num1 < num2 ) return -1;
        }
        return 0; 
    }
}

Leetcode 66. Plus One. 【Easy】
只分為兩種情況括丁,一是999,而是其他史飞。
其他,就用for循環(huán)倒序遍歷來解決构资。

class Solution {
    public int[] plusOne(int[] digits) {
        for(int i=digits.length-1; i>=0; i--){
            if(digits[i]<9){
                digits[i]++;
                return digits;
            } else {
                digits[i] = 0;
            }
        }
        int[] newDigits = new int[digits.length+1];
        newDigits[0] = 1;
        return newDigits;
    }
}

Leetcode 8. String to Integer (atoi) 【Medium】
判斷str.charAt(0),用start記錄數(shù)字開始的位置吐绵。遍歷。

class Solution {
    public int myAtoi(String str) {
        str = str.trim();
        if(str == null || str.length() == 0) return 0;
        long res = 0; 
        int start = 0; 
        int sign = 1; 
        if(str.charAt(0) == '+'){
            start++;
        } else if (str.charAt(0) == '-'){
            sign = -1;
            start++;
        }
        for(int i = start; i< str.length();i++){
            if(!Character.isDigit(str.charAt(i))){
                return (int)res * sign;
            }
            res = res * 10 + str.charAt(i) - '0';
            if(sign==1 && res>=Integer.MAX_VALUE) return Integer.MAX_VALUE;
            if(sign==-1 && res>Integer.MAX_VALUE) return Integer.MIN_VALUE;
        }
        return (int)res * sign;
    }
}

Leetcode 258. Add Digits. 【Easy】
常規(guī)暴力解法己单。Time: O(n), Space: O(1).

class Solution {
    public int addDigits(int num) {
        int sum = 0;
        while(true){
            sum = 0;
            while(num>0){
                sum += num % 10;
                num /= 10;
            }
            num = sum;
            if(sum<10) break;
        }
        return sum;
        
    }
}

找規(guī)律:以9為循環(huán)


num對應(yīng)的result以9為循環(huán).jpg
class Solution {
    public int addDigits(int num) {
        return (num - 1) % 9 + 1;
    }
}

Leetcode 67. Add Binary 【Easy】
倒序遍歷兩個數(shù)組纹笼。用while(i>=0 || j>=0)作為判斷,用remainder記錄進(jìn)位苟跪。
Time: O(n), Space: O(n).

class Solution {
    public String addBinary(String a, String b) {
        StringBuilder sb = new StringBuilder();
        int i = a.length() - 1;
        int j = b.length() - 1;
        int remainder = 0, sum = 0;
        while(i>=0 || j>=0){
            sum = remainder;
            if(i>=0) sum += a.charAt(i--) -'0';
            if(j>=0) sum += b.charAt(j--) -'0';
            sb = sb.insert(0,sum%2);     
            //如果用sb.append(num%2),就要在最后return sb.reverse().toString()
            remainder = sum/2;  
        }
        if(remainder != 0) sb = sb.insert(0,remainder);
        return sb.toString();
    }
}

Leetcode 43. Multiply Strings. 【Medium】
題目要求4: You must not use any built-in BigInteger library or convert the inputs to integer directly. 不能直接用long,int等牍疏。
兩個for循環(huán),倒序遍歷鳞陨,每次計(jì)算兩個一位數(shù)的乘積,累加到new int[]對應(yīng)位置

class Solution {
    public String multiply(String num1, String num2) {
        int[] digits = new int[num1.length()+num2.length()];  //想清楚這里
        for(int i=num1.length()-1; i>=0; i--){
            for(int j=num2.length()-1; j>=0; j--){
                int product = (num1.charAt(i)-'0') * (num2.charAt(j)-'0'); //注意要 -'0'
                int index1 = i + j, index2 = index1 + 1;   //想清楚這里 
                int sum = product + digits[index2]; 
                digits[index2] = sum % 10;    
                digits[index1] += sum / 10;    // 注意是 +=
            }
        }
        
        String res = new String();   // 用String 或 StringBuilder都行
        for(int digit: digits){
            if(!(res.length() == 0 && digit == 0)){   //第一個加入res的必須是非零數(shù)
               res += digit; 
            } 
        }
        System.out.println(res);
        return res.length() == 0? "0": res;        
    }
}

Leetcode 29. Divide Two Integers 【Medium】
這題考了左移的操作厦滤。用 divideHelper 測試dividend 能裝多少個divisor歼狼,用的while()循環(huán),實(shí)際上是類似二分查找羽峰。
注意:把兩個負(fù)數(shù)傳入divideHelper添瓷,是因?yàn)?MIN_VALUE 絕對值比 MAX_VALUE 大1,如果 abs(MIN_VALUE) 會越界鳞贷。所以干脆傳兩個負(fù)數(shù)進(jìn)helper.

class Solution {
    public int divide(int dividend, int divisor) {
        //負(fù)數(shù)左移,也是相當(dāng)于*2,直到小于MIN_VALUE,就越界成為正數(shù)(不規(guī)則的正數(shù))
        if(dividend == Integer.MIN_VALUE && divisor == -1) return Integer.MAX_VALUE;
        boolean isSameSign = (dividend <0) == (divisor<0);
        int res = divideHelper(-Math.abs(dividend),-Math.abs(divisor));        
        return isSameSign ? res : -res;
    }
    
    private int divideHelper(int dividend, int divisor){
        int res = 0;
        int currentDivisor = divisor;
        while(dividend<=divisor){   // abs(divisor) <= abs(dividend)
            int temp = 1;            
            while((currentDivisor << 1)>=dividend && (currentDivisor << 1)<0 ){ //test max temp for: temp * abs(divisor) <= abs(dividend), while temp = 2^n
                temp <<=1;
                currentDivisor <<=1;
            }
            dividend -= currentDivisor;
            res += temp;
            currentDivisor = divisor;   //將currentDivisor恢復(fù)為divisor
        }       
        return res;
    }    
}

Leetcode 69. Sqrt(x). 【Easy】
這題搀愧,需要寫出兩種情況:1) 二分法;2) 牛頓法咱筛。
二分法:Time: O(logn), Space: O(1).

class Solution {
    public int mySqrt(int x) {
        if(x<=0) return 0;
        int low = 1, high = x;
        while(low<=high){
            long mid = (high - low)/2 + low;
            if(mid * mid == x){     // mid * mid 可能越界,所以應(yīng)該設(shè)置mid為long迅箩。比如當(dāng)x=MAX_VALUE, 第一次計(jì)算mid^2就必然越界
                return (int)mid;
            } else if (mid * mid > x){
                high = (int)mid - 1;
            } else {
                low = (int)mid + 1;
            }
        }
        return high;
        // if(high * high < x){ //必定的結(jié)果
        //     return high;
        // } 
        // return 0;
    }
}

牛頓法:
牛頓法,又名切線法饲趋。

CSDN搜索: leetcode:Sqrt(x) 牛頓迭代法求整數(shù)開方
https://blog.csdn.net/newfelen/article/details/23359629

draw a tangent line for function f(x), the tangent line and x axis intersects at point( xn+1, 0). So the tangent line passes both (xn, f(xn)) and (xn+1, 0). We can get the equation for the tangent line, which is ...

公式推導(dǎo):
經(jīng)過 (xn+1,0), ( xn, f(xn) ) 且斜率為f'(xn) 的直線,直線表達(dá)式為:
( f(xn)-0 ) / (xn - xn+1) = f'(xn) , 化簡得到:


牛頓法的迭代公式.jpg

而本題 f(xn) = x^2 - n, f' = 2x. 所以,
xn+1 = xn - (x^2-n)/2x
= (x + n/x)/2.
牛頓法的Time Complexity 是unstable 不穩(wěn)定的投队,可以理解為 接近O(logn).

public int mySqrt(int x){
    long res = x; 
    while( res * res > x){
        res = ( res + x / res ) / 2 ; 
    }
    return (int)res;
}

Leetcode 367. Valid Perfect Square. 【Easy】
這題,需要寫出兩種情況:1) 二分法敷鸦;2) 牛頓法。
二分法:Time: O(logn), Space: O(1).

class Solution {
    public boolean isPerfectSquare(int num) {
        int low = 1, high = num;
        while(low<=high){
            long mid = (high - low)/2 + low;
            if(mid * mid == num){     // mid * mid 可能越界扒披,所以應(yīng)該設(shè)置mid為long。比如當(dāng)x=MAX_VALUE, 第一次計(jì)算mid^2就必然越界
                return true; 
            } else if (mid * mid < num){
                low = (int)mid + 1;
            } else {
                high = (int)mid - 1;
            }     
        }
        return false;
    }
}

牛頓法:Time 是 uncertain碟案,但在這題可理解為優(yōu)于O(nlogn).

class Solution {
    public boolean isPerfectSquare(int num) {
        long x = num;
        while(x * x > num){
            x = (x + num/x)/2;
        }
        return x * x == num;
    }
}

Leetcode 50. Pow(x, n) 【Medium】

Time: O(logn), Space: O(1).
本題暴力解法就是O(n), 要提升,必然是二分法价说,提升到O(logn).
用Iterative方法,每次while循環(huán)鳖目,讓n降低到一半,并對x進(jìn)行平方领迈。
注意:min的絕對值大于max絕對值碍沐,所以Integer.MIN_VALUE的絕對值會越界衷蜓;所以要用long值記錄n的絕對值。

class Solution {
    public double myPow(double x, int n) {
        if(n==0) return 1;
        long abs = Math.abs((long)n);
        double res = 1;
        while(abs >0){
            if(abs%2 != 0) {
                res *= x;
            }
            x *= x;
            abs /= 2;
        }
        if(n<0) {
            return 1/res;
        } else {
            return res;
        }       
    }
}

【不推薦】用Recursive方法做恍箭。

    public double myPow(double x, int n) {
        return n<0? 1/helper(x,-n):helper(x,n);                
    }
       
    private double helper(double x, int n){
        if(n==0) return 1;
        double y = helper(x,n/2);
        if(n%2 != 0){
            return y * y * x;
        } else {
            return y * y;
        }
    }

Leetcode 365. Water and Jug Problem 【Medium】
這是純數(shù)學(xué)問題。只有當(dāng)z%(x和y的最大公約數(shù))==0 時才為true扯夭。
math theory 鏈接:Bézout's identity 數(shù)學(xué)家 Mathematician 讀音:/'bezu/ 貝祖

class Solution {
    public boolean canMeasureWater(int x, int y, int z) {
        if(x+y<z) return false;
        if(x==z || y==z || x+y==z) return true;
        return z % gcd(x,y) == 0;
    }
    //輾轉(zhuǎn)相除法,iterative方法交洗。
    public int gcd(int a, int b){
        while(b!=0){
            int temp = b;
            b = a%b;
            a = temp;
        }
        return a;
    }
}

輾轉(zhuǎn)相除法,英文是Euclidean Algorithm,歐幾里得算法构拳。【ju??kl?di?n】
最大公約數(shù)的Recursive寫法:

    public int gcd(int a, int b){
        if(b==0) return a;
        return gcd(b,a%b);
    }

Leetcode 204 Count Primes 【Easy】
構(gòu)建一個boolean[] 用來記錄每個數(shù)是否為prime置森。外層for循環(huán)遍歷數(shù)組,內(nèi)層for循環(huán), 改變 i的倍數(shù)對應(yīng)的boolean凫海,從而得到每個數(shù)是否為prime的信息。

class Solution {
    public int countPrimes(int n) {
        boolean[] notPrime = new boolean[n+1]; //j<=n/i情況下用n+1.若是i*j<n,用n就行
        int res = 0;
        for(int i=2;i<n;i++){
            if(notPrime[i]==false){
                res++;
                // System.out.println(i);
                for(int j=2;j<=n/i;j++){   //或者: (int j=2,i*j<n,j++)也可
                    notPrime[i*j] = true;
                }
            }
        }
        return res;
    }
}

Leetcode 1. Two Sum. 【Easy】
經(jīng)典題行贪,用HashMap來記錄前面存在的值和對應(yīng)位置漾稀。for循環(huán)遍歷至某值建瘫,查詢target-該值在map中是否存在。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res = new int[]{-1,-1};
        Map<Integer,Integer> map = new HashMap<>();
        for(int i=0; i<nums.length; i++){
            if(map.containsKey(target-nums[i])){
                res[0] = map.get(target-nums[i]);
                res[1] = i;
                break;
            }
            map.put(nums[i],i);
        }
        return res;
    }
}

Leetcode 167. Two Sum II - Input array is sorted. 【Easy】
Time: O(n).
題目:已經(jīng)排序完畢殷蛇。
經(jīng)典題,參考了二分法的步驟橄浓,但這里是right--或left++,每次只移動一步

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int left = 0, right = numbers.length-1;
        while(left<right){
            if(numbers[left]+numbers[right]==target){
                return new int[]{left+1,right+1};
            } else if(numbers[left]+numbers[right]>target){
                right--;
            } else {
                left++;
            }
        }
        return new int[]{-1,-1};
    }
}

Leetcode 15. 3Sum. 【Medium】
Time: O(n2).
題目沒排序贮配。要用二分法思想,需要先排序泪勒。只有在從小到大排序好的數(shù)組中宴猾,才能移動left和right叼旋,而且才能達(dá)到避免duplicate的目的。
參考Leetcode 167. 同樣是運(yùn)用了二分法的思想夫植。難點(diǎn)在于怎么把三個數(shù)之和轉(zhuǎn)化為兩個數(shù)之和。
要避免duplicate重復(fù)详民,首先需要排序。用Arrays.sort() 排序沈跨。
然后第一層for循環(huán)遍歷數(shù)組由捎,第二層while用left和right狞玛,遍歷該數(shù)右邊的子數(shù)組。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0; i<nums.length-2; i++){
            if(i>0 && nums[i]==nums[i-1]) continue; //避免duplicate的關(guān)鍵1
            int left = i+1, right = nums.length-1;
            int sum = 0 - nums[i];
            while(left<right){
                if(nums[left]+nums[right]==sum){
                    res.add(Arrays.asList(nums[i],nums[left],nums[right]));  //Arrays.asList().  
                    //兩個while循環(huán)是避免duplicate的關(guān)鍵2
                    while(left<right && nums[left+1]==nums[left]) left++;    //left<right是防止越界
                    while(left<right && nums[right-1]==nums[right]) right--; //left<right是防止越界
                    left++;
                    right--;
                } else if(nums[left]+nums[right]>sum){
                    right--;
                } else {
                    left++;
                }
            }
        }
        return res;
    }
}

Leetcode 16.
題目沒排序心肪。要用二分法思想,需要先排序硬鞍。只有在從小到大排序好的數(shù)組中,才能移動left和right膳凝。

class Solution {
    public int threeSumClosest(int[] nums, int target) {
        int res = nums[0] + nums[1] + nums[2];
        Arrays.sort(nums);
        for(int i=0; i<nums.length-2;i++){
            int left = i+1, right = nums.length-1;
            while(left<right){
                int sum = nums[i]+nums[left]+nums[right];
                if(Math.abs(sum-target)<Math.abs(res-target)){
                    res = sum;
                }
                if(sum>target){
                    right--;
                } else {
                    left++;
                }
            }
        }
        return res;
    }
}

Leetcode 259. 3Sum Smaller 【Medium】

class Solution {
    public int threeSumSmaller(int[] nums, int target) {
        int res = 0; 
        Arrays.sort(nums);
        for(int i=0;i<nums.length-2;i++){
            int left = i+1, right = nums.length-1;
            while(left<right){
                int sum = nums[i]+nums[left]+nums[right];
                if(sum<target){
                    res += right-left; //特定的i,特定的left,right(right可以一直左移到left+1,共right-left個)
                    left++;        //測試下一個left
                } else {
                    right--; //right左移恭陡,直到找到符合條件的right使得sum<target
                }
            }
        }
        return res;        
    }
}

Leetcode 18. 4Sum. 【Medium】

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> list = new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0;i<nums.length-3;i++){
            if(i>0 && nums[i]==nums[i-1]) continue;
//比3Sum多了一個for和一句continue
            for(int j=i+1; j<nums.length-2;j++){
                if(j>i+1 && nums[j]==nums[j-1]) continue;
                int left = j+1, right = nums.length-1;
                while(left<right){
                    int sum = nums[i]+nums[j]+nums[left]+nums[right];
                    if(sum==target){
                        list.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));
                        while(left<right && nums[left+1]==nums[left])   left++;
                        while(left<right && nums[right-1]==nums[right]) right--;
                        left++;
                        right--;
                    } else if(sum<target){
                        left++;
                    } else {
                        right--;
                    }   
                }                
            }
        }
        return list;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末上煤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子劫狠,更是在濱河造成了極大的恐慌,老刑警劉巖独泞,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異懦砂,居然都是意外死亡蜒犯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門罚随,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人淘菩,你說我怎么就攤上這事〕备模” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵进陡,是天一觀的道長。 經(jīng)常有香客問我趾疚,道長,這世上最難降的妖魔是什么糙麦? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮赡磅,結(jié)果婚禮上魄缚,老公的妹妹穿的比我還像新娘焚廊。我一直安慰自己,他們只是感情好咆瘟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著袒餐,像睡著了一般飞蛹。 火紅的嫁衣襯著肌膚如雪灸眼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天焰宣,我揣著相機(jī)與錄音,去河邊找鬼匕积。 笑死逻澳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的斜做。 我是一名探鬼主播瓤逼,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼霸旗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起戚揭,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎民晒,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潜必,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年磁滚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垂攘。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖晒他,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仪芒,我是刑警寧澤唁影,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布掂名,位于F島的核電站哟沫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏嗜诀。R本人自食惡果不足惜猾警,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望发皿。 院中可真熱鬧,春花似錦穴墅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽松捉。三九已至夹界,卻和暖如春隘世,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背丙者。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蔓钟,地道東北人。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓滥沫,卻偏偏與公主長得像侣集,于是被迫代替她去往敵國和親兰绣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容