Java基礎

劍指offer java刷一遍
http://www.lxweimin.com/p/010410a4d419

image.png

清晰 https://www.zhihu.com/question/36914829

StringBuffer 和 StringBuilder

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.Stack;
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        Stack<Integer> stack = new Stack<>();
        while (listNode != null) {
            stack.push(listNode.val);
            listNode = listNode.next;
        }
 
        ArrayList<Integer> list = new ArrayList<>();
        while (!stack.isEmpty()) {
            list.add(stack.pop());
        }
        return list;       
    }
}
兩個棧實現隊列

import java.util.Stack;

public class stack_queue {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();

    public void push(int node) {
        stack1.push(node);
    }

    public int pop() {
        if(stack2.isEmpty()){
            while(!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
            return stack2.pop();
        }else {
            return stack2.pop();
        }
    }
}

旋轉數組的最小元素

用二分法,二分法為了簡便可以一直使用 start + 1 < end,但需要判斷最后兩個元素值。

import java.util.ArrayList;
public class Solution {
   public int minNumberInRotateArray(int [] array) {
        if(array==null||array.length==0){
            return 0;
        }
        int start = 0;
        int end = array.length - 1;
        int mid = 0;
        while (start + 1 < end){
            mid = start + (end - start) / 2;
            if(array[mid] > array[end]){
                start = mid + 1;
            }else{
                end = mid;
            }
        }
        if(array[start] < array[end])
            return array[start];
        else
            return array[end];
    }
}
跳臺階問題
public class Solution {
    public int JumpFloor(int target) {
        if(target <= 2){
            return target;
        }
        int pre = 2;
        int prepre = 1;
        int temp = 0;
        for(int i=3;i<target+1;i++){
            temp = pre;
            pre = pre + prepre;
            prepre = temp;
        }
        return pre;
    }
}

1的個數

   public int NumberOf1(int n) {
        int count = 0;
        if(n >= 0){
            while(n!=0){
                count = count + (n & 1);
                n = (n>>1);
            }
        }else {
            n = ~n;
            while(n!=0){
                count = count + (n & 1);
                n = (n>>1);
            }
            count = 32 - count;
        }
        return count;
    }

另一種巧妙方法

public class Solution {
    public int NumberOf1(int n) {
        int count = 0;
        while(n!= 0){
            count++;
            n = n & (n - 1);
         }
        return count;
    }
}

如果一個整數不為0,那么這個整數至少有一位是1。如果我們把這個整數減1,那么原來處在整數最右邊的1就會變為0,原來在1后面的所有的0都會變成1(如果最右邊的1后面還有0的話)。其余所有位將不會受到影響。
舉個例子:一個二進制數1100,從右邊數起第三位是處于最右邊的一個1。減去1后,第三位變成0,它后面的兩位0變成了1,而前面的1保持不變,因此得到的結果是1011.我們發現減1的結果是把最右邊的一個1開始的所有位都取反了。這個時候如果我們再把原來的整數和減去1之后的結果做與運算,從原來整數最右邊一個1那一位開始所有位都會變成0。如1100&1011=1000.也就是說,把一個整數減去1,再和原整數做與運算,會把該整數最右邊一個1變成0.那么一個整數的二進制有多少個1,就可以進行多少次這樣的操作。

算法提升篇

求連續子數組的最大和--動態規劃

public class maxSumofContinueArray {
    public static int FindGreatestSumOfSubArray(int[] array) {
        int max = array[0];
        int preMax = 0;
        for(int i=0;i<array.length;i++){
            if(preMax >= 0)
                preMax = preMax + array[i];
            else
                preMax = array[i];
            if(preMax > max)
                max = preMax;
        }
        return max;
    }
    public static void main(String [] args){
        int[] data = {1,-2,3,10,-4,7,2,-5};
        System.out.println(FindGreatestSumOfSubArray(data));
    }
}

剪繩子

public class cutRope {
    public static int maxCutting(int length){
        if(length <= 1) return 0;
        if(length < 4) return length - 1;
        int []res = new int[length+1];
        res[0] = 0;
        res[1] = 1;
        res[2] = 2;
        res[3] = 3;
        int max = 0;
        int temp = 0;
        for(int i=4; i<=length; i++){
            max = 0;
            for(int j=1;j<=i/2;j++){
                temp = res[j]*res[i-j];
                if(temp > max) max = temp;
            }
            res[i] = max;
        }
        return res[length];
    }
}
數組翻譯成字符串

0對應a,25對應z,給定一個整數,看有多少種對應方式。動態規劃的典型問題。

public class numberToString {
    public static int getTranslationCount(int number){
        if(number < 0) return 0;
        return getTranslationCount(Integer.toString(number));
    }
    public static int getTranslationCount(String number){
        int pre = 1;
        int prepre = 1;
        int temp = 0, g = 1;
        for(int i=number.length()-2;i>=0;i--){
            if(Integer.parseInt(number.charAt(i)+""+number.charAt(i+1))<26 && number.charAt(i) != '0'){
                g = 1;
            } else{
                g = 0;
            }
            temp = pre;
            pre = pre + g*prepre;
            prepre = temp;
        }
        return pre;
    }
    public static void main(String[] args){
        System.out.println(getTranslationCount(1204));
    }
}
最長不重復子串
public class maxLengthOfNoDup {
    public static int longestSubstringWithoutdup(String str){
        if(str==null || str.length()==0)
            return 0;
        int[] dp = new int[str.length()];
        dp[0] = 1;
        int max = 1;
        for(int i=1;i<dp.length;i++){
            int j=i-1;
            for(;j>=i-dp[i-1];j--){
                if(str.charAt(i) == str.charAt(j))
                    break;
            }
            dp[i] = i - j;
            if(dp[i]>max)
                max = dp[i];
        }
        return max;
    }
    public static void main(String[] args){
        System.out.println(longestSubstringWithoutdup("arabcadecefr"));
    }
}

關鍵在于這句的理解 (;j>=i-dp[i-1];j--)。
這道題還是需要認真理解,首先為什么不能夠直接從j=i-1一直遍歷到j=0,因為要保證遍歷的范圍是不重復的,比如[2,3,2,4,5,6],對4來說和前面三個都不相等,但是里面就有2重復,需要根據前面一個的最大范圍確定所能遍歷的范圍。遍歷到j=m時加入相等,則會停止,計算元素個數是i-j+1,這里沒有+1,因為for循環先對j進行了減1操作。

矩陣中的路徑(回溯)
public class PathInArray {
    public static boolean hasPath(char[][] data, String str){
        if(data==null || data.length==0 || str==null || str.length()==0)
            return false;
        int m = data.length;
        int n = data[0].length;
        boolean[][] visted = new boolean[m][n];
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                visted[i][j] = false;
            }
        }
        boolean res;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                res = dfs(data,visted,i,j,str,0);
                if(res)
                    return true;
            }
        }
        return false;
    }
    private static boolean dfs(char[][] data,boolean[][] visted,int m, int n , String str, int pos){
        if(pos==str.length()) return true;
        if(m<0 || m >= data.length || n < 0 || n >= data[0].length)
            return false;
        if(visted[m][n] || data[m][n] != str.charAt(pos)) return false;
        visted[m][n] = true;
        boolean res = dfs(data,visted,m+1,n,str,pos+1) ||
        dfs(data,visted,m-1,n,str,pos+1) ||
        dfs(data,visted,m,n-1,str,pos+1) ||
        dfs(data,visted,m,n+1,str,pos+1);
        visted[m][n] = false;
        return res;
    }
    public static void main(String[] args){
        char[][] data = {
            {'a','b','t','g'},
            {'c','f','c','s'},
            {'j','d','e','h'}
        };
        System.out.println(hasPath(data,"bfce"));
        System.out.println(hasPath(data,"abfb"));
    }
}
機器人的運動范圍
public class robotMoveRange {
    public static int movingCount(int threshold, int cow, int row){
        if(threshold < 0 || cow < 0 || row < 0)
            return 0;
        boolean[][] visted = new boolean[cow][row];
        for(int i=0;i<cow;i++){
            for(int j=0;j<row;j++){
                visted[i][j] = false;
            }
        }
        int count = 0;
        dfs(count,threshold, visted, cow, row, 0, 0);
        // 返回的count=0,出現問題。整數是傳值
        return count;
    }
    public static void dfs(int count, int threshold, boolean[][] visted, int cow, int row, int m, int n){
        if( m < 0 || m>=cow || n<0 || n>=row) return;
        if(visted[m][n]) return;
        visted[m][n] = true;
        if(getDigitSum(m) + getDigitSum(n) <= threshold) {
            count += 1;
            System.out.println(count); //最終結果正確
        }
        dfs(count, threshold, visted, cow, row, m-1, n);
        dfs(count, threshold, visted, cow, row, m+1, n);
        dfs(count, threshold, visted, cow, row, m, n+1);
        dfs(count, threshold, visted, cow, row, m, n-1);

    }
    public static int getDigitSum(int number){
        int sum = 0;
        while(number!=0){
            sum += number % 10;
            number /= 10;
        }
        return sum;
    }
    public static void main(String[] args){
        System.out.println(movingCount(9,2,20));
    }
}

上面的程序有一點問題。如何去改進。

public class robotMoveRange {
    public static int movingCount(int threshold, int cow, int row){
        if(threshold < 0 || cow < 0 || row < 0)
            return 0;
        boolean[][] visted = new boolean[cow][row];
        for(int i=0;i<cow;i++){
            for(int j=0;j<row;j++){
                visted[i][j] = false;
            }
        }
        int count = 0;
        count = dfs(threshold, visted, cow, row, 0, 0);
        // 返回的count=0,出現問題。整數是傳值
        return count;
    }
    public static int dfs( int threshold, boolean[][] visted, int cow, int row, int m, int n){
        if( m < 0 || m>=cow || n<0 || n>=row) return 0;
        if(visted[m][n] || (getDigitSum(m) + getDigitSum(n) > threshold)) return 0;
        visted[m][n] = true;
        return dfs(threshold, visted, cow, row, m-1, n) +
        dfs( threshold, visted, cow, row, m+1, n) +
        dfs( threshold, visted, cow, row, m, n+1) +
        dfs(threshold, visted, cow, row, m, n-1) + 1;

    }
    public static int getDigitSum(int number){
        int sum = 0;
        while(number!=0){
            sum += number % 10;
            number /= 10;
        }
        return sum;
    }
    public static void main(String[] args){
        System.out.println(movingCount(9,2,20));
    }
}
一個數的整數次方


public class xPowerN {
    public static double mypower(double number, int n){
        if(n==0) return 1;
        if(n < 0){
            double res = mypower(number,-n);
            return 1.0/res;
        }else {
            double temp = mypower(number,n>>1);
            if((n & 1)==1){
                return temp * temp * number;
            }else
                return temp * temp;
        }
    }
    public static double mypower2(double number, int n){
        double res = 1;
        int abs_n = Math.abs(n);
        while(abs_n!=0){
            if((abs_n & 1) == 1)
                res *= number;
            abs_n >>= 1;
            number *= number;
        }
        if(number < 0) return 1.0/res;
        else return res;
    }
    public static void main(String[] args){
        double base = 2;
        int n = 10;
        System.out.println(mypower2(base, n));
    }
}

遞歸和循環兩種基本思路。

排序鏈表刪除重復元素

import com.ListNode;

import java.util.List;

// 刪除排序鏈表重復節點,不保留
public class DeleteNodeInLinklist {
    public static ListNode DeleteDupNode(ListNode node){
        if(node==null || node.next==null)
            return node;
        ListNode dummy = new ListNode(-1);
        dummy.next = node;
        ListNode ptr = dummy;
        while(node != null && node.next != null){
            if(node.val != node.next.val){
                node = node.next;
                ptr = ptr.next;
            }else {
                while((node != null) && (node.next != null) && (node.val==node.next.val)){
                    node = node.next;
                }
                node = node.next;
                ptr.next = node;
            }
        }
        return dummy.next;
    }
    // 刪除重復節點但保留一個
    public static ListNode DeleteDupNodeWithOne(ListNode node){
        if(node==null || node.next==null)
            return node;
        ListNode current = node;
        while(current != null && current.next != null){
            if(current.val == current.next.val)
                current.next = current.next.next;
            else
                current = current.next;
        }
        return node;
    }
}

BFS

樹的按層遍歷

隊列相關知識 https://juejin.im/post/5a3763ed51882506a463b740

public class BTlevelOrderTravelsal {
    public  List<List<Integer>> levelOrder(TreeNode root){
        List<List<Integer>> res = new ArrayList<>();
        if(root == null) return res;
        // LinkedList ?
        Queue<TreeNode> nodes = new LinkedList<>();
        nodes.offer(root);
        while(!nodes.isEmpty()){
            List<Integer> subres = new ArrayList<>();
            int levelNum = nodes.size();
            for(int i=0;i<levelNum;i++){
                TreeNode node = nodes.poll();
                subres.add(node.val);
                if(node.left != null) nodes.offer(node.left);
                if(node.right != null) nodes.offer(node.right);
            }
            res.add(subres);
        }
        return res;
    }
}
之字形層次打印二叉樹
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if(root == null) return res;

        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        boolean order = true;
        int size = 1;

        while(!q.isEmpty()) {
            List<Integer> tmp = new ArrayList<>();
            for(int i = 0; i < size; ++i) {
                TreeNode n = q.poll();
                if(order) {
                    tmp.add(n.val);
                } else {
                    tmp.add(0, n.val);
                }
                if(n.left != null) q.add(n.left);
                if(n.right != null) q.add(n.right);
            }
            res.add(tmp);
            size = q.size();
            order = order ? false : true;
        }
        return res;      
    }
}

Remove Invalid Parentheses (leetcode 301)

https://leetcode.com/problems/remove-invalid-parentheses/description/

public class Solution {
    public List<String> removeInvalidParentheses(String s) {
        List<String> res = new ArrayList<>();
        if (s == null){
            return res;
        }
        Set<String> visited = new HashSet<>();
        Queue<String> queue = new LinkedList<>();
        queue.offer(s);
        visited.add(s);
        boolean found = false;

        while (!queue.isEmpty()){
            String item = queue.poll();
            if(isVaild(item)){
                res.add(item);
                found = true;
            }
            if(found) continue;
            for(int i=0; i<item.length();i++){
               if(item.charAt(i) != '(' && item.charAt(i) !=')') continue;
               String t = item.substring(0,i) + item.substring(i+1);
               if(!visited.contains(t)){
                   queue.offer(t);
                   visited.add(t);
               }
            }
        }
        return res;
    }
        
    public static boolean isVaild(String s){
        int count = 0;
        for(int i=0; i<s.length();i++){
            if(s.charAt(i)=='(') count += 1;
            if(s.charAt(i)==')' && count-- == 0) return false;

        }
        return count == 0;
    }
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內容

  • Win7下如何打開DOS控制臺? a:開始--所有程序--附件--命令提示符 b:開始--搜索程序和文件--cmd...
    逍遙嘆6閱讀 1,605評論 4 12
  • 50道經典Java編程練習題,將數學思維運用到編程中來。抱歉哈找不到文章的原貼了,有冒犯的麻煩知會聲哈~ 1.指數...
    OSET我要編程閱讀 6,986評論 0 9
  • 01奇數求和練習 A: 奇數求和練習a: 題目分析為了記錄累加和的值,我們需要定義一個存儲累加和的變量我們要獲取到...
    Tyihou閱讀 549評論 0 0
  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執行單位為行(line),也就是一...
    悟名先生閱讀 4,184評論 0 13
  • “常回家看看,回家看看,媽媽準備了一些嘮叨,爸爸張羅了一桌好飯。生活的煩惱和媽媽說說,工作的事情向爸爸談談……”多...
    Miya小桶閱讀 488評論 0 2