力扣---2020.6.6

128. 最长连续序列

//时间复杂度  O(nlon(n))  不符合题意
class Solution {
    public int longestConsecutive(int[] nums) {
        if(nums==null||nums.length==0) return 0;
        Arrays.sort(nums);
        int max = 1;
        int count = 1;
        for(int i=1;i<nums.length;i++){
            if((nums[i-1]+1)==nums[i]){
                count++;
            }else if(nums[i]==nums[i-1]){
                continue;
            }else{
                max = Math.max(max,count);
                count = 1;
            }
        }
        max = Math.max(max,count);
        return max;
    }
}
class Solution {
    public int longestConsecutive(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for(int num:nums){
            set.add(num);
        }

        int max = 0;
        for(int num:nums){
            if(set.remove(num)){
                int currentLongest = 1;
                int current = num;
                while(set.remove(current-1)) current--;
                currentLongest += (num-current);

                current = num;;
                while(set.remove(current+1)) current++;

                currentLongest += (current-num);
                max = Math.max(max,currentLongest);
            }
        }
        return max;
    }
}
//并查集
class Solution {
    Map<Integer, Integer> parents = new HashMap<>();
    Map<Integer, Integer> count = new HashMap<>();

    // 带路径压缩的找上司
    public int find(int x){
        int p = parents.get(x);
        if(p == x)
            return p;
        // t为x的最终boss
        int t = find(p);
        // 直接将x的上司设置为t,将路径压缩
        parents.put(x, t);
        return t;
    }

    // 将x与y联合
    public void union(int x, int y){
        int p1 = find(x);
        int p2 = find(y);
        if(p1 == p2)
            return;
        // 若x与y的上司不是同一个人,则设置p2为p1的上司
        parents.put(p1, p2);
        // 此时p2手下的人数就为p1手下管理的人数加p2手下的人数
        count.put(p2, count.get(p1) + count.get(p2));
    }

    public int longestConsecutive(int[] nums) {
        int ans = 0;
        Set<Integer> set = new HashSet<>();
        // set去重,同时初始化parents和count
        for(int num : nums){
            parents.put(num, num);
            count.put(num, 1);
            set.add(num);
        }
        for(int num : set){
            if(set.contains(num-1))
                union(num, num-1);
            if(set.contains(num+1))
                union(num, num+1);
            // 查找num的最终boss的管理人数与当前ans相比,留最大
            ans = Math.max(ans, count.get(find(num)));
        }
        return ans;
    }
}

面试题 08.02. 迷路的机器人

class Solution {
    private List<List<Integer>> ans = new ArrayList<>();
    public List<List<Integer>> pathWithObstacles(int[][] obstacleGrid) {
        return dfs(0, 0, obstacleGrid) ? ans : new ArrayList<>();
    }

    private boolean dfs(int i, int j, int[][] grid) {
        if (i >= grid.length || j >= grid[0].length || grid[i][j] == 1) return false;
        ans.add(Arrays.asList(i, j));
        if (i == grid.length - 1 && j == grid[0].length - 1) return true;
        boolean can = dfs(i + 1, j, grid) || dfs(i, j + 1, grid);
        if (!can) {
	        ans.remove(ans.size() - 1);
	        grid[i][j] = 1;  // 向下向右走都不行,说明当前节点也是故障节点
        }
        return can;
    }
}

面试题 10.03. 搜索旋转数组

class Solution {
    public int search(int[] arr, int target) {
        for(int i = 0;i<arr.length;i++){
            if(arr[i]==target){
                return i;
            }
        }
        return -1;
    }
}
class Solution {
    public int search(int[] arr, int target) {
        int n=arr.length;
        while(n>1&&arr[n-1]==arr[0]) n--;
        //求最小值的索引
        int l=0,r=n-1;
        while(l<r){
            int mid=(l+r)>>1;
            if(arr[mid]<=arr[r]) r=mid;
            else l=mid+1;
        }
        //求target的索引
        r=l+n-1;
        if(target<arr[l]) return -1;
        while(l<r){
            int mid=(l+r)>>1;
            if(arr[mid%n]>=target) r=mid;
            else l=mid+1;
        }
        if(arr[l%n]==target) return l%n;
        return -1;
    }
}
class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        if (right == -1)
            return -1;
        while (left < right) {                                         // 循环结束条件left==right
            int mid = left + (right - left) / 2;
            if (nums[left] < nums[mid]) {                              // 如果左值小于中值,说明左边区间升序               
                if (nums[left] <= target && target <= nums[mid]) {     // 如果目标在左边的升序区间中,右边界移动到mid
                    right = mid;                                       
                } else {                                               // 否则目标在右半边,左边界移动到mid+1
                    left = mid + 1;                                    
                }
            } else if (nums[left] > nums[mid]) {                       // 如果左值大于中值,说明左边不是升序,右半边升序
                if (nums[left] <= target || target <= nums[mid]) {     // 如果目标在左边,右边界移动到mid
                    right = mid;                                       
                } else {                                               // 否则目标在右半边,左边界移动到mid+1
                    left = mid + 1;                                    
                }
            } else if (nums[left] == nums[mid]) {                      // 如果左值等于中值,可能是已经找到了目标,也可能是遇到了重复值
                if (nums[left] != target) {                            // 如果左值不等于目标,说明还没找到,需要逐一清理重复值。
                    left++;
                } else {                                               // 如果左值等于目标,说明已经找到最左边的目标值 
                    right = left;                                      // 将右边界移动到left,循环结束
                }
            }
        }
        return (nums[left] == target) ? left : -1;                     // 返回left,或者-1
    }
}

你知道的越多,你不知道的越多。

你可能感兴趣的:(数据结构与算法)