【精選】JAVA算法題(二十)

一、異位詞

題目:

/**
 * 給定兩個字符串 s 和 t ,編寫一個函數來判斷 t 是否是 s 的一個字母異位詞。
 *
 * 示例 1:
 * 輸入: s = "anagram", t = "nagaram"
 * 輸出: true
 *
 * 示例 2:
 * 輸入: s = "rat", t = "car"
 * 輸出: false
 *
 * 說明:
 * 你可以假設字符串只包含小寫字母。
 */

 大體意思是說兩個字符串,把其中一個字符串中的一個或幾個字母換個位置就和另一個字符串相等了。

既然換字母就能讓兩個字符串相等,那麼他們就有相同的字母,可以先排序再比對。

    public static boolean method1(String s, String t) {
        char[] sChars = s.toCharArray();
        char[] tChars = t.toCharArray();
        Arrays.sort(sChars);
        Arrays.sort(tChars);
        return String.valueOf(sChars).equals(String.valueOf(tChars));
    }

用Map對每個字母的出現次數進行統計再檢查另一個字符串,消費,看最後Map是否爲空

    public static boolean method2(String s, String t) {
        Map<Character, Integer> map = new HashMap<>();
        for (char ch : s.toCharArray()) {
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }
        for (char ch : t.toCharArray()) {
            Integer count = map.get(ch);
            if (count == null) {
                return false;
            } else if (count > 1) {
                map.put(ch, count - 1);
            } else {
                map.remove(ch);
            }
        }
        return map.isEmpty();
    }

把字符串轉換成Ascll碼當數組下標使,同樣是統計數量進行比對。

    public static boolean method3(String s, String t) {
        int[] sCounts = new int[26];
        int[] tCounts = new int[26];
        for (char ch : s.toCharArray()) {
            sCounts[ch - 'a']++;
        }
        for (char ch : t.toCharArray()) {
            tCounts[ch - 'a']++;
        }
        for (int i = 0; i < 26; i++) {
            if (sCounts[i] != tCounts[i]) {
                return false;
            }
        }
        return true;
    }

二、二叉樹的路徑

題目:

/**
 * 給定一個二叉樹,返回所有從根節點到葉子節點的路徑。
 * 說明: 葉子節點是指沒有子節點的節點。
 *
 * 示例:
 * 輸入:
 * <p>
 *     1
 *  /   \
 * 2     3
 *  \
 *   5
 *
 * 輸出: ["1->2->5", "1->3"]
 * 解釋: 所有根節點到葉子節點的路徑爲: 1->2->5, 1->3
 */
public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int x) {
        val = x;
    }
}

這題一看就需要遍歷樹的知識了,而且用遞歸更爲簡單,不斷保留當前已經遍歷的路徑並不斷添加新的節點,直到到達葉子節點才加入list.

    List<String> res = new ArrayList<String>();
    public List<String> method1(TreeNode root) {
        if(root == null)
            return res;
        if(root.left == null && root.right == null){
            res.add(root.val + "");
        }
        if(root.left != null){
            fun(root.left, root.val + "");
        }
        if(root.right != null){
            fun(root.right, root.val + "");
        }

        return res;
    }

    /**
     * 遞歸判斷當前節點是不是葉子節點
     * 參數 root 爲當前節點,str 爲該節點前的路徑
     * 若遇到葉子節點,則加入res中;若非葉子節點,則繼續往下走
     */
    public void fun(TreeNode root, String str){
        if(root == null)
            return;
        if(root.left == null && root.right == null)
            res.add(str + "->" + root.val);
        if(root.left != null){
            fun(root.left, str + "->" + root.val);
        }
        if(root.right != null){
            fun(root.right, str + "->" + root.val);
        }
    }

三、迴旋鏢

題目:

/**
 * 迴旋鏢定義爲一組三個點,這些點各不相同且不在一條直線上。
 * 給出平面上三個點組成的列表,判斷這些點是否可以構成迴旋鏢。
 *
 * 示例 1:
 * 輸入:[[1,1],[2,3],[3,2]]
 * 輸出:true
 *
 * 示例 2:
 * 輸入:[[1,1],[2,2],[3,3]]
 * 輸出:false
 */

 關鍵點:三點不共線,這個證明我們初中都學過,如何判斷我寫在註釋裏面了,需要判斷的異常條件便是同時兩個點在X軸或者Y軸。

    /**
     * 三點共線條件
     * A(x1,y1)、B(x2,y2)、C(x3,y3)
     * AB斜率:kAB=(y2-y1)/(x2-x1)
     * BC斜率:kBC=(y3-y2)/(x3-x2)
     * 計算結果可得:kAB=kBC。
     */
    public static boolean isBoomerang(int[][] points) {
        if ((points[0][0]==points[1][0]&&points[0][1]==points[1][1])||
                (points[0][0]==points[2][0]&&points[0][1]==points[2][1])||
                (points[1][0]==points[2][0]&&points[1][1]==points[2][1])){
            return false;
        }
        double x2x1=points[1][0]-points[0][0];
        double x3x2=points[2][0]-points[1][0];
        double y2y1=points[1][1]-points[0][1];
        double y3y2=points[2][1]-points[1][1];
        double kAB=0,kBC=0;
        if (x2x1==0){
            kAB=Integer.MAX_VALUE;
        }else {
            kAB=y2y1/x2x1;
        }
        if (x3x2==0){
            kBC=Integer.MAX_VALUE;
        }else {
            kBC=y3y2/x3x2;
        }
        if ((kAB==Integer.MAX_VALUE&&kBC==0)||(kAB==0&&kBC==Integer.MAX_VALUE)){
            return true;
        }
        if (kAB==kBC){
            return false;
        }
        return true;
    }

四、數字加和

題目:

/**
 * 給定一個非負整數 num,反覆將各個位上的數字相加,直到結果爲一位數。
 *
 * 示例:
 * 輸入: 38
 * 輸出: 2
 * 解釋: 各位相加的過程爲:3 + 8 = 11, 1 + 1 = 2。 由於 2 是一位數,所以返回 2。
 *
 * 進階:
 * 你可以不使用循環或者遞歸,且在 O(1) 時間複雜度內解決這個問題嗎?
 */

最笨的方法就是循環,不斷把每一位取出來放到list裏面,最後加和,你也可以自己定義變量在分離每一位的時候就進行加和並最後進行賦值操作。

    public static int method1(int num) {
        ArrayList<Integer> integers=new ArrayList<>();
        while (num>9){
            while (num!=0){
                integers.add(num%10);
                num/=10;
            }
            for (int a:integers){
                num+=a;
            }
            integers.clear();
        }
        return num;
    }

當然我們要挑戰一下進階條件,不適用循環和遞歸,並在時間複雜度0(1)解決這個問題,那這就需要找尋規律了。

假如一個三位數'abc',其值大小爲s1 = 100 * a + 10 * b + 1 * c,經過一次各位相加後, 變爲s2 = a + b + c,減小的差值爲(s1 -s2) = 99 * a + 9 * b,差值可以被9整除,每一個循環都這樣,縮小了9的倍數。 當num小於9,即只有一位時,直接返回num,大於9時,如果能被9整除,則返回9(因爲不可能返回0也不可能返回兩位數及以上的值), 如果不能被整除,就返回被9除的餘數。

    public static int method2(int num) {
        return num==0?0:num%9==0?9:num%9;
    }

很簡潔,下面這種意思一樣

    public static int method3(int num) {
        if (num > 9){
            num = num % 9;
            if(num == 0){
                return 9;
            }
        }
        return num;
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章