目录
一.单词搜索(深度优先遍历)
1.题目
2.思路图解
3.代码
二.集合中的所有子集(子集有序且不能有重复元素)
1.题目
2.图解
3.代码
三.求滑动窗口中的最大值
1.题目
2.思路图解
3.代码
四.下一个排列
1.题目
2.思路图解
3.代码实现
五.组合总和(二)
1.题目
2.图解思路
3.代码
六.三数之和
1.题目
2.思路图解
3.代码
七.搜索旋转排序数组
1.题目
2.思路图解
3.代码
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/word-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例:
public boolean exist(char[][] board, String word) {
boolean[][] valid = new boolean[board.length][board[0].length];
//每一个位置开始进行寻找
for(int i=0; i=b.length || j>=b[0].length) {
return false;
}
//当前位置已经访问过
if(valid[i][j] ==true) {
return false;
}
//当前字符不匹配
if(str.charAt(begin) != b[i][j]) {
return false;
}
//找到
if(begin == str.length()-1) {
return true;
}
//当前字符匹配,从该字符开始上下左右依次进行寻找
valid[i][j] = true;
boolean f = dfs(b, str, i+1, j, begin+1, valid) ||
dfs(b, str, i-1, j, begin+1, valid) ||
dfs(b, str, i, j+1, begin+1, valid) ||
dfs(b, str, i, j-1, begin+1, valid);
//如果找到就放回true
if(f==true) {
return true;
}
//没找到,回溯到上一个位置,继续寻找
valid[i][j] = false;
return false;
}
给定一个整数数组 nums ,其中可能包含重复元素,请你返回这个数组的所有可能子集。
返回的答案中不能包含重复的子集,将答案按字典序进行排序。
示例:
输入:[1,2]
返回值:[[],[1],[1,2],[2]]
ArrayList> res = new ArrayList<>();
public ArrayList> subsets (int[] nums) {
//保持子集有序,需要先进行排序
Arrays.sort(nums);
dfs(nums,0, new ArrayList<>());
return res;
}
public void dfs(int[] nums, int begin, ArrayList list) {
//添加每一个创建的有序子集放到结果集合中
res.add(new ArrayList<>(list));
for(int i=begin; ibegin && nums[i]==nums[i-1]) {
continue;
}
//添加元素到子集合中
list.add(nums[i]);
//以当前元素为起点依次向后进行处理
dfs(nums, i+1, list);
//删除当前集合最后一个结点
list.remove(list.size()-1);
}
}
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值
如图所示:
借助优先级队列存储最大值,借助数组来存储当前元素索引位置,之后根据计算判断该优先级队列堆顶元素是否在滑动窗口内。
public int[] maxSlidingWindow(int[] nums, int k) {
//使用优先级队列和数组(数组中存储值和索引位置,通过索引位置判断是否最大元素在窗口中
//不在就进行删除)
//建立大堆
PriorityQueue queue = new PriorityQueue<>((int[] a1, int[] a2)->{
return a1[0]==a2[0]?a2[1]-a1[1]:a2[0]-a1[0];
});
//先存储一部分滑动窗口的值
for(int i=0; i
给定一个数组,将数组重新排列,得到一系列数组排列S,请你从S中,找出恰好比当前数组排列字典序大于1的数组排列。
1.[1,2,3]的得到的数组排列S有:[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]。
2.该题数组排列的字典序大小排序规则:2个数组排列的元素按顺序比较,直到数组元素不相等为止,不相等的第一个元素,谁的元素大,谁的字典序比较大,比如数组a=[1,2,3]与数组b=[1,3,2]比较:a[0]=b[0],a[1]
3.如果不存在更大的数组排列,则返回最小的数组排列。
示例:
输入:[1,2,3]
返回值:[1,3,2]
思路:
首先从后往前找第一个非递减的位置(目的是为了让最近位置的元素变大,从而使影响的变化最小)。
然后再从后面找第一个比当前位置元素大的值(最后面是低位,影响的结果值最小),将这两个位置的元素进行交换(说明该结果就变大了)。
再将该元素后面的所有元素进行反转(因为刚开始找的位置的元素肯定比后一个元素值小,进行交换后,该元素到了后面,为了增加的最少,反转之后,大的值就到了后面)。
图解:
public int[] nextPermutation (int[] nums) {
int n = nums.length;
int i = n-2;
int j = n-1;
int k = n-1;
//从后向前找,首先找非递减的第一个数,然后找比当前数大的最后出现的元素
//然后再将第一个出现得数得后面的反转即可
while(i>=0 && nums[i]>=nums[j]) {
i--;
j--;
}
if(i>=0) {
while(nums[i]>nums[k]) {
k--;
}
swap(nums, i, k);
}
reverse(nums, j, n-1);
return nums;
}
//交换指定位置的元素
public void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//反转指定位置的元素
public void reverse(int[] arr, int beign, int end) {
while(beign
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/combination-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例:
输入: candidates = [2,5,2,1,2], target = 5, 输出:[[1,2,2], [5]]
List list = new ArrayList<>();
List> res = new ArrayList<>();
public List> combinationSum2(int[] candidates, int target) {
//先排序
Arrays.sort(candidates);
dfs(candidates, target, 0);
return res;
}
public void dfs(int[] arr, int target, int index) {
//求得结果值,加入结果集中
if(target==0) {
res.add(new ArrayList<>(list));
return;
}
//依次向后处理每一位数字
for(int i=index; iindex && arr[i]==arr[i-1]) {
continue;
}
//没有超过结果,加入到临时结果集中
list.add(arr[i]);
//继续向下一层进行递归处理
dfs(arr, target-arr[i], i+1);
//说明当前层当前位置的元素已经处理完成,删除掉处理当前层的下一个元素
list.remove(list.size()-1);
}
}
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]]
首先对数组进行排序,然后再固定一个元素(如果前一个元素和当前元素相等,就跳过当前元素,相当于去重),另外两个元素从当前元素的后面进行寻找,寻找的方法是使用双指针来进行寻找,如果固定元素+左边界元素+右边界元素>0,说明需要左移右边界;如果<0,就需要右移左边界;如果相等,就将结果存储在结果集中,存储之后,还需要判断左边界的后一个是否和左边界相等,右边界的前一个是否和右边界相等,如果有相等的,就移动边界,相当于去重,之后处理完当前左右边界的元素后,同时移动左右边界继续寻找满足的结果集。
public List> threeSum(int[] nums) {
Arrays.sort(nums);
List> res = new ArrayList<>();
//思路:固定一个元素,然后寻找另外两个元素
for(int i=0; i0 && nums[i]==nums[i-1]) continue;
int left = i+1;
int right = nums.length-1;
while(left list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[left]);
list.add(nums[right]);
res.add(list);
//去重
while(left
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/search-in-rotated-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例:
输入:nums = [4,5,6,7,0,1,2], target = 4 输出:0
由于二分查找只能在有序的数组区间中进行查找,所以根据这个思路来进行求解。根据题意得,如果将一个有序旋转过的数组分成两份,一部分的元素全部有序,一部分的元素部分有序,我们可以根据需要查找的元素和有序数组区间的首尾进行比较,如果在当前有序序列中,就缩小为当前有序范围;否则可能在另一部分的数组中。
public int search(int[] nums, int target) {
//在有序的数组区间中进行查找
int left = 0;
int right = nums.length;
while(left=target) {
//说明结果值在有序的一边
right = mid;
}else {
//说明结果值在无序的一边
left = mid+1;
}
}else {
//说明右边有序
if(nums[mid]<=target && nums[right-1]>=target) {
//说明在右边有序的序列中
left = mid+1;
}else {
//说明在无序的左边
right = mid;
}
}
}
return -1;
}