1. 程式人生 > 其它 >HIGH高頻H1(1-10)

HIGH高頻H1(1-10)

技術標籤:algorithm

HIGH.1無重複字元的最長子串

給定一個字串,請你找出其中不含有重複字元的最長子串的長度。

示例1:

輸入: s = "abcabcbb"
輸出: 3
解釋: 因為無重複字元的最長子串是 "abc",所以其長度為 3。
示例 2:

輸入: s = "bbbbb"
輸出: 1
解釋: 因為無重複字元的最長子串是 "b",所以其長度為 1。
示例 3:

輸入: s = "pwwkew"
輸出: 3
解釋: 因為無重複字元的最長子串是"wke",所以其長度為 3。

請注意,你的答案必須是 子串 的長度,"pwke"是一個子序列,不是子串。
示例 4:

輸入: s = ""
輸出: 0

提示:

0 <= s.length <= 5 * 104
s由英文字母、數字、符號和空格組成

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int res = 0;
        Set<Character> set = new HashSet<>();
        for(int l = 0, r = 0; r < s.length(); r++) {
            char c = s.charAt(r);
            while(set.contains(c)) {
                set.remove(s.charAt(l++));
            }
            set.add(c);
            res = Math.max(res, r - l + 1);
        }

        return res;
    }
}

HIGH.2簡化路徑

以 Unix 風格給出一個檔案的絕對路徑,你需要簡化它。或者換句話說,將其轉換為規範路徑。

在 Unix 風格的檔案系統中,一個點(.)表示當前目錄本身;此外,兩個點 (..)表示將目錄切換到上一級(指向父目錄);兩者都可以是複雜相對路徑的組成部分。更多資訊請參閱:Linux / Unix中的絕對路徑 vs 相對路徑

請注意,返回的規範路徑必須始終以斜槓 / 開頭,並且兩個目錄名之間必須只有一個斜槓 /。最後一個目錄名(如果存在)不能以 / 結尾。此外,規範路徑必須是表示絕對路徑的最短字串。

示例 1:

輸入:"/home/"
輸出:"/home"

解釋:注意,最後一個目錄名後面沒有斜槓。
示例 2:

輸入:"/../"
輸出:"/"
解釋:從根目錄向上一級是不可行的,因為根是你可以到達的最高階。
示例 3:

輸入:"/home//foo/"
輸出:"/home/foo"
解釋:在規範路徑中,多個連續斜槓需要用一個斜槓替換。
示例 4:

輸入:"/a/./b/../../c/"
輸出:"/c"
示例 5:

輸入:"/a/../../b/../c//.//"
輸出:"/c"
示例 6:

輸入:"/a//bc/d//././/.."
輸出:"/a/b/c"

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/simplify-path
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

public String simplifyPath(String path) {
    Stack<String> stack = new Stack<>();
    String[] items = path.split("/");
    for (String item : items) {
        if (item.isEmpty() || item.equals(".")) continue;
        if (item.equals("..")) {
            if (!stack.empty()) stack.pop();
        } else {
            stack.push(item);
        }
    }
    return "/" + String.join("/", stack);
}

HIGH.3復原IP 地址

給定一個只包含數字的字串,復原它並返回所有可能的 IP 地址格式。

有效的 IP 地址 正好由四個整數(每個整數位於 0 到 255 之間組成,且不能含有前導 0),整數之間用 '.' 分隔。

例如:"0.1.2.201" 和 "192.168.1.1" 是 有效的 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "[email protected]" 是 無效的 IP 地址。

示例 1:

輸入:s = "25525511135"
輸出:["255.255.11.135","255.255.111.35"]
示例 2:

輸入:s = "0000"
輸出:["0.0.0.0"]
示例 3:

輸入:s = "1111"
輸出:["1.1.1.1"]
示例 4:

輸入:s = "010010"
輸出:["0.10.0.10","0.100.1.0"]
示例 5:

輸入:s = "101023"
輸出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]

提示:

0 <= s.length <= 3000
s 僅由數字組成

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/restore-ip-addresses
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

class Solution {
    public List<String> restoreIpAddresses(String s) {
        List<String> res = new ArrayList();
        List<String> temp = new ArrayList();
        helper(res,temp,s);
        return res;
    }

    void helper(List<String> res,List<String> temp,String next) {
        if(temp.size() > 4) {
            return;
        }
        if(temp.size() == 4 && next.length() == 0) {
            String ip = temp.get(0) + "." + temp.get(1) + "." + temp.get(2) + "." + temp.get(3);
            res.add(ip);
            return;
        }
        for(int i = 0; i < next.length(); i++) {
            String s = next.substring(0,i+1);
            if(s.length() > 1 && s.charAt(0) == '0') {
                continue;
            } 
            if(s.length() > 3) {
                continue;
            }
            if(s.length() == 3 && "255".compareTo(s) < 0) {
                continue;
            }
            temp.add(s);
            helper(res,temp,next.substring(i+1));
            temp.remove(temp.size() - 1);
        }
    }
}

HIGH.4三數之和

給你一個包含 n 個整數的陣列nums,判斷nums中是否存在三個元素 a,b,c ,使得a + b + c = 0 ?請你找出所有滿足條件且不重複的三元組。

注意:答案中不可以包含重複的三元組。

示例:

給定陣列 nums = [-1, 0, 1, 2, -1, -4],

滿足要求的三元組集合為:
[
[-1, 0, 1],
[-1, -1, 2]
]

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/3sum
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> ls = new ArrayList<>();
 
        for (int i = 0; i < nums.length - 2; i++) {
            if (i == 0 || (i > 0 && nums[i] != nums[i - 1])) {  // 跳過可能重複的答案
 
                int l = i + 1, r = nums.length - 1, sum = 0 - nums[i];
                while (l < r) {
                    if (nums[l] + nums[r] == sum) {
                        ls.add(Arrays.asList(nums[i], nums[l], nums[r]));
                        while (l < r && nums[l] == nums[l + 1]) l++;
                        while (l < r && nums[r] == nums[r - 1]) r--;
                        l++;
                        r--;
                    } else if (nums[l] + nums[r] < sum) {
                        while (l < r && nums[l] == nums[l + 1]) l++;   // 跳過重複值
                        l++;
                    } else {
                        while (l < r && nums[r] == nums[r - 1]) r--;
                        r--;
                    }
                }
            }
        }
        return ls;
    }
}

HIGH.5島嶼的最大面積

給定一個包含了一些 0 和 1 的非空二維陣列grid 。

一個島嶼是由一些相鄰的1(代表土地) 構成的組合,這裡的「相鄰」要求兩個 1 必須在水平或者豎直方向上相鄰。你可以假設grid 的四個邊緣都被 0(代表水)包圍著。

找到給定的二維陣列中最大的島嶼面積。(如果沒有島嶼,則返回面積為 0 。)

示例 1:

[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
對於上面這個給定矩陣應返回6。注意答案不應該是 11 ,因為島嶼只能包含水平或垂直的四個方向的 1 。

示例 2:

[[0,0,0,0,0,0,0,0]]
對於上面這個給定的矩陣, 返回0。

注意:給定的矩陣grid的長度和寬度都不超過 50。

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/max-area-of-island
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

class Solution {
    public int maxAreaOfIsland(int[][] grid) {
        int max = 0;
        for(int i = 0; i < grid.length; i++){
            for(int j = 0; j < grid[0].length; j++){
                if(grid[i][j] == 1){
                    max = Math.max (dfs(grid, i, j), max);
                }
            }
        }
        return max;
    }
    int dfs(int[][] grid, int i, int j){
        if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == 0){
            return 0;
        }
        grid[i][j] = 0;
        int count = 1;
        count += dfs(grid, i+1, j);
        count += dfs(grid, i-1, j);
        count += dfs(grid, i, j+1);
        count += dfs(grid, i, j-1);
        return count;
    }
}

HIGH.6搜尋旋轉排序陣列

給你一個整數陣列 nums ,和一個整數 target 。

該整數陣列原本是按升序排列,但輸入時在預先未知的某個點上進行了旋轉。(例如,陣列[0,1,2,4,5,6,7]可能變為[4,5,6,7,0,1,2] )。

請你在陣列中搜索target ,如果陣列中存在這個目標值,則返回它的索引,否則返回-1。


示例 1:

輸入:nums = [4,5,6,7,0,1,2], target = 0
輸出:4
示例2:

輸入:nums = [4,5,6,7,0,1,2], target = 3
輸出:-1
示例 3:

輸入:nums = [1], target = 0
輸出:-1

提示:

1 <= nums.length <= 5000
-10^4 <= nums[i] <= 10^4
nums 中的每個值都 獨一無二
nums 肯定會在某個點上旋轉
-10^4 <= target <= 10^4

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/search-in-rotated-sorted-array
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

思路:如果中間的數小於最右邊的數,則右半段是有序的,若中間數大於最右邊數,則左半段是有序的,我們只要在有序的半段裡用首尾兩個陣列來判斷目標值是否在這一區域內,這樣就可以確定保留哪半邊了

class Solution {
    public int search(int[] nums, int target) {
        int len = nums.length;
        int left = 0, right = len-1;
        while(left <= right){
            int mid = (left + right) / 2;
            if(nums[mid] == target)
                return mid;
            else if(nums[mid] < nums[right]){
                if(nums[mid] < target && target <= nums[right])
                    left = mid+1;
                else
                    right = mid-1;
            }
            else{
                if(nums[left] <= target && target < nums[mid])
                    right = mid-1;
                else
                    left = mid+1;
            }
        }
        return -1;
    }
}

HIGH.7朋友圈

班上有N名學生。其中有些人是朋友,有些則不是。他們的友誼具有是傳遞性。如果已知 A 是 B的朋友,B 是 C的朋友,那麼我們可以認為 A 也是 C的朋友。所謂的朋友圈,是指所有朋友的集合。

給定一個N * N的矩陣M,表示班級中學生之間的朋友關係。如果M[i][j] = 1,表示已知第 i 個和 j 個學生互為朋友關係,否則為不知道。你必須輸出所有學生中的已知的朋友圈總數。

示例 1:

輸入:
[[1,1,0],
[1,1,0],
[0,0,1]]
輸出:2
解釋:已知學生 0 和學生 1 互為朋友,他們在一個朋友圈。
第2個學生自己在一個朋友圈。所以返回 2 。
示例 2:

輸入:
[[1,1,0],
[1,1,1],
[0,1,1]]
輸出:1
解釋:已知學生 0 和學生 1 互為朋友,學生 1 和學生 2 互為朋友,所以學生 0 和學生 2 也是朋友,所以他們三個在一個朋友圈,返回 1 。

提示:

1 <= N <= 200
M[i][i] == 1
M[i][j] == M[j][i]

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/friend-circles
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

class Solution {
    
    public int findCircleNum(int[][] M) {
        /**
        使用一個visited陣列, 依次判斷每個節點, 如果其未訪問, 朋友圈數加1並對該節點進行dfs搜尋標記所有訪問到的節點
        **/
        boolean[] visited = new boolean[M.length];
        int ret = 0;
        for(int i = 0; i < M.length; ++i) {
            if(!visited[i]) {
                dfs(M, visited, i);
                ret++;
            }
        }
        return ret;
    }
    
    private void dfs(int[][] m, boolean[] visited, int i) {
        for(int j = 0; j < m.length; ++j) {
            if(m[i][j] == 1 && !visited[j]) {
                visited[j] = true;
                dfs(m, visited, j);
            }
        }
    }
}

HIGH.8接雨水

給定n 個非負整數表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。

示例 1:

輸入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
輸出:6
解釋:上面是由陣列 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。
示例 2:

輸入:height = [4,2,0,3,2,5]
輸出:9

提示:

n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/trapping-rain-water
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

class Solution {
    public int trap(int[] height) {
        int min = 0 , max = 0 ;
        int l = 0, r = height.length-1;
        
        int res = 0;
        while(l < r){
            min = height[height[l] < height[r] ? l++:r--];
            max = Math.max(min,max);
            res += max - min;
        }
        return res;
    }
}

HIGH.9反轉連結串列

定義一個函式,輸入一個連結串列的頭節點,反轉該連結串列並輸出反轉後連結串列的頭節點。

示例:

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL

限制:

0 <= 節點個數 <= 5000

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

迭代

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null, cur = head, next = null;
        while(cur != null) {
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
}

遞迴

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null) {
            return head;
        }
        ListNode node = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return node;
    }
}

HIGH.10 兩數相加

給出兩個非空 的連結串列用來表示兩個非負的整數。其中,它們各自的位數是按照逆序的方式儲存的,並且它們的每個節點只能儲存一位數字。

如果,我們將這兩個數相加起來,則會返回一個新的連結串列來表示它們的和。

您可以假設除了數字 0 之外,這兩個數都不會以 0開頭。

示例:

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/add-two-numbers
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

維護一個進位變數t

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode dummyHead = new ListNode(-1), pre = dummyHead;
        int t = 0;
        while (l1 != null || l2 != null || t != 0) {
            if (l1 != null) {
                t += l1.val;
                l1 = l1.next;
            }
            if (l2 != null) {
                t += l2.val;
                l2 = l2.next;
            }
            pre.next = new ListNode(t % 10);
            pre = pre.next;
            t /= 10;
        }

        return dummyHead.next;
    }
}