leetcode

1、组合

给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

示例:

输入: n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

package leetcode;

import java.util.ArrayList;
import java.util.List;

public class combine_77 {

    public static void main(String[] args) {
        int n = 4;
        int k = 2;
        List<List<Integer>> res = combine(n, k);
        System.out.println(res);
    }

    static List<List<Integer>> list2 = new ArrayList<>();
    static List<Integer> list = new ArrayList<>();

    public static List<List<Integer>> combine(int n, int k) {
        if (n <= 0 || k <= 0 || n < k) {
            return list2;
        }
        combine1(n,k,1);
        return list2;
    }

    public static void combine1(int n,int k,int index) {
        if (k == list.size()) {
            list2.add(new ArrayList<>(list));
            return;
        }
        //k - pre.size() 是剩下还要寻找的数的个数。
        for(int i=index;i<=n-(k-list.size())+1;i++) {
            list.add(i);
            combine1(n,k,i+1);
            list.remove(list.size()-1);
        }

    }

}

2、子集

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: nums = [1,2,3]
输出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []

package leetcode;

import java.util.ArrayList;
import java.util.List;

public class subsets_78 {

    public static void main(String[] args) {
        int[] nums = { 1, 2, 3 };
        List<List<Integer>> res =subsets(nums);
        System.out.println(res);
    }

    static List<List<Integer>> list2 = new ArrayList<>();
    static List<Integer> list = new ArrayList<>();

    public static List<List<Integer>> subsets(int[] nums) {
        list2.add(new ArrayList<>(list));
      //如果数组包含重复元素加上这句
              //Arrays.sort(nums);
        combine(nums, 0, nums.length);
        return list2;
    }

    public static void combine(int[] nums,int start,int end) {
        for(int i=start;i<end;i++) {
        
                   //如果数组包含重复元素加上这句
        //   if(i>start&&nums[i]==nums[i-1]){
             //   continue;
            //     }
            list.add(nums[i]);
            list2.add(new ArrayList<>(list));
            combine(nums,i+1,end);
            list.remove(list.size()-1);
        }
    }
}

 3、单词搜索

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

 

示例:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false
package leetcode;

public class wordSearch_80 {

    public static void main(String[] args) {
        char[][] board = { { 'A', 'B', 'C', 'E' }, { 'S', 'F', 'E', 'S' }, { 'A', 'D', 'E', 'E' } };
        String word = "ABCESEEEFS";
        System.out.println(exist(board, word));
    }

    public static boolean exist(char[][] board, String word) {
        int m = board.length;
        int n = board[0].length;
        int x = 0;
        char[][] boardCopy = new char[m + 2][n + 2];
        for (int i = 0; i < board[0].length; i++) {
            boardCopy[0][i] = ' ';
            boardCopy[boardCopy.length - 1][i] = ' ';
        }
        for (int i = 0; i < boardCopy.length; i++) {
            boardCopy[i][0] = ' ';
            boardCopy[i][boardCopy[0].length - 1] = ' ';
        }
        for (int i = 1; i < boardCopy.length - 1; i++) {
            for (int j = 1; j < boardCopy[0].length - 1; j++) {
                boardCopy[i][j] = board[i - 1][j - 1];
            }
        }

        for (int i = 1; i < boardCopy.length; i++) {
            for (int j = 1; j < boardCopy[0].length; j++) {
                if (word.charAt(x) == boardCopy[i][j]) {
                    boolean[][] used = new boolean[m+2][n+2];
                    boolean res = find(boardCopy, word, i, j, x,used);
                    if(res) {
                        return res;
                    }
                }
            }
        }
        return false;

    }

    public static boolean find(char[][] boardCopy, String word, int i, int j, int x,boolean[][] used) {

        if (x == word.length()) {
            return true;
        } else {
            if (used[i][j]==false&&word.charAt(x++) == boardCopy[i][j]) {
                used[i][j]=true;
                if (find(boardCopy, word, i + 1, j, x,used)) {//
                    return true;
                } else if (find(boardCopy, word, i, j + 1, x,used)) {//
                    return true;
                } else if (find(boardCopy, word, i - 1, j, x,used)) {//
                    return true;
                } else if (find(boardCopy, word, i, j - 1, x,used)) {//
                    return true;
                } else {
                    used[i][j]=false;
                    return false;
                }
            } else {
                return false;
            }

        }
    }

}

 4、 删除排序数组中的重复项 II

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定 nums = [1,1,1,2,2,3],

函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,1,2,3,3],

函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。

你不需要考虑数组中超出新长度后面的元素。
方法:覆盖多余的重复项
算法:
    我们使用了两个指针,i 是遍历指针,指向当前遍历的元素;j 指向下一个要覆盖元素的位置。
    同样,我们用 count 记录当前数字出现的次数。count 的最小计数始终为 1。
    我们从索引 1 开始一次处理一个数组元素。
    若当前元素与前一个元素相同,即 nums[i]==nums[i-1],则 count++。若 count > 2,则说明遇到了多余的重复项。在这种情况下,我们只向前移动 i,而 j 不动。
    若 count <=2,则我们将 i 所指向的元素移动到 j 位置,并同时增加 i 和 j。
    若当前元素与前一个元素不相同,即 nums[i] != nums[i - 1],说明遇到了新元素,则我们更新 count = 1,并且将该元素移动到 j 位置,并同时增加 i 和 j。
    当数组遍历完成,则返回 j。
package leetcode;
//删除排序数组中的重复项(leetcode 80)
public class removeDuplicates_80 {

    public static void main(String[] args) {
        int[] arr= {1,2,2,2,2,3,3,3,3}; 
        System.out.println(removeDuplicates(arr));
        for(int i:arr) {
            System.out.print(i+" ");
        }
    }
    public static int removeDuplicates(int[] nums) {
       int j=1;int count=1;
       for(int i=1;i<nums.length;i++) {
           if(nums[i]==nums[i-1]) {
               count++;
           }else {
               count=1;
           }
           if(count<=2) {
               nums[j++]=nums[i];
           }
       }
       return j;
    }
}

5. 搜索旋转排序数组 II

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。

编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false

示例 1:

输入: nums = [2,5,6,0,0,1,2], target = 0
输出: true

示例 2:

输入: nums = [2,5,6,0,0,1,2], target = 3
输出: false
解题思路:
本题是需要使用二分查找,怎么分是关键,举个例子:
    第一类
    101111011110111 和 111011110111101 这种。此种情况下 nums[start] == nums[mid],分不清到底是前面有序还是后面有序,此时 start++ 即可。相当于去掉一个重复的干扰项。
    第二类
    222 333 444 555 666 777 111 这种,也就是 nums[start] < nums[mid]。此例子中就是 2 < 5;
    这种情况下,前半部分有序。因此如果 nums[start] <=target<nums[mid],则在前半部分找,否则去后半部分找。
    第三类
    666 777 111 222 333 444 555 这种,也就是 nums[start] > nums[mid]。此例子中就是 6 > 2;
    这种情况下,后半部分有序。因此如果 nums[mid] <target<=nums[end]。则在后半部分找,否则去前半部分找。

class Solution {
    public boolean search(int[] nums, int target) {
        if(nums.length==0)return false;
        int start=0;
        int end=nums.length-1;
        int mid;
        while(start<=end){
            mid=start+(end-start)/2;
            if(nums[mid]==target){
                return true;
            }
            if(nums[start]==nums[mid]){
                start++;
                continue;
            }
            if(nums[start]<nums[mid]){
                if(nums[start]<=target&&nums[mid]>target){
                    end=mid-1;
                }else{
                    start=mid+1;
                }
            }
            else if(nums[start]>nums[mid]){
                if(nums[mid]<target&&nums[end]>=target){
                    start=mid+1;
                }else{
                    end=mid-1;
                }
            }
        }
        return false;
    }
}

 



posted @ 2020-06-30 15:26  我们村里的小花儿  阅读(134)  评论(0编辑  收藏  举报