HIGH高頻H1(1-10)

augfun發表於2020-12-15

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" 和 "192.168@1.1" 是 無效的 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;
    }
}

 

相關文章