leetcode25
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路一:按部就班,顺序每k个元素进行一次翻转,由此,拆解为 单个长度为k的小链表完全翻转,和将整个列表处理成长度为k的小链(就地翻转)
1.长度为k的链表翻转部分
首先要理解链表翻转的本质,即如果t指向当前需要翻转的节点,则需要将t指向t.next的指针指向t的前一个节点(单向链表),为了翻转的连续进行,则需要在翻转前保存pre和next两个指针
这就是一个链表翻转的过程,由于end之后不一定为null,所以控制条件需要注意:
//单个列表反转
public static ListNode reverseOne(ListNode start,ListNode end){
if(start==null||end == null)return null;
ListNode pre=null,t=start,next = t;
while(t!=null&&pre!=end){
next = t.next;
//调整指针
t.next = pre;
//更新上面的量
pre = t;
t = next;
}
return end;
}
2.整个链表按照长度为k进行翻转
//按k个为一组进行反转
public static ListNode reverseKGroup(ListNode head, int k) {
ListNode start= head,end=null;
ListNode v = new ListNode();
ListNode pre = v,next;
ListNode h = head;
for(int c=0;h!=null;h=next,c++){
next = h.next;
if(c%k==0)start = h;
if(c%k==k-1) {
//标记end
end = h;
reverseOne(start,end);
//处理指针
start.next = next;
pre.next = end;
pre = start;
}
}
return v.next;
}
题解
class Solution {
//单个列表反转
public static ListNode reverseOne(ListNode start,ListNode end){
if(start==null||end == null)return null;
ListNode pre=null,t=start,next = t;
while(t!=null&&pre!=end){
next = t.next;
//调整指针
t.next = pre;
//更新上面的量
pre = t;
t = next;
}
return end;
}
public ListNode reverseKGroup(ListNode head, int k) {
ListNode start= head,end=null;
ListNode v = new ListNode();
ListNode pre = v,next;
ListNode h = head;
for(int c=0;h!=null;h=next,c++){
next = h.next;
if(c%k==0)start = h;
if(c%k==k-1) {
//标记end
end = h;
reverseOne(start,end);
//处理指针
start.next = next;
pre.next = end;
pre = start;
}
}
return v.next;
}
}
leetcode 30
给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
示例 1:
输入:
s = "barfoothefoobarman",
words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:
输入:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
输出:[]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
单词长度都一样,提示采用滑动窗口
需要注意:
- 滑动外层是按照字符个数
- 滑动内层是按照单词
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res = new ArrayList<>();
if(words.length==0)return res;
int wl = words[0].length();
if(s.length()<wl)return res;
//统计单词表中的个数
Map<String,Integer> wordSet = new HashMap<>();
for(String word:words){
wordSet.put(word,wordSet.getOrDefault(word,0)+1);
}
//注意滑动不是按单词长度而是按字符
for(int i=0;i<wl;i++){
int start=i,end=i,cnt =0;
//统计字符串中出现的个数
Map<String,Integer> wordMap = new HashMap<>();
//内层按照单词长度开始滑动
while(end+wl<=s.length()){
String word = s.substring(end, end+wl);
end +=wl;
//不含有该单词
if(!wordSet.keySet().contains(word)){
cnt =0;
start = end;
wordMap.clear();//中间不能有间隔
}
//含有该单词
else{
wordMap.put(word, wordMap.getOrDefault(word,0)+1);
cnt++;
while(wordMap.get(word)>wordSet.get(word)){
String popWord = s.substring(start,start+wl);
start += wl;
cnt--;
wordMap.put(popWord, wordMap.get(popWord)-1);
}
if(cnt==words.length)res.add(start);
}
}
}
return res;
}
}
leetcode 37
编写一个程序,通过填充空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。
一个数独。
答案被标成红色。
提示:
给定的数独序列只包含数字 1-9 和字符 '.' 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sudoku-solver
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路一: 回溯法
lass Solution {
boolean[][] cols = new boolean[9][9];
boolean[][] rows = new boolean[9][9];
boolean[][][] blocks = new boolean[3][3][9];
List<Integer[]> spaces = new ArrayList<>();
boolean valid = false;
public void solveSudoku(char[][] board) {
for(int y =0;y<9;y++){
for(int x=0;x<9;x++){
if(board[y][x]=='.'){
spaces.add(new Integer[]{y,x});
}
else{
int digit = board[y][x]-'1';
rows[y][digit]=true;
cols[x][digit]=true;
blocks[y/3][x/3][digit]=true;
}
}
}
dfs(board,0);
}
public void dfs(char[][] board,int step){
if(step==spaces.size()){
valid = true;
return;
}
Integer[] space = spaces.get(step);
Integer i = space[0],j = space[1];
for(int digit = 0;digit<9&&!valid;digit++){
if(!cols[j][digit]&&!rows[i][digit]&&!blocks[i/3][j/3][digit]){
cols[j][digit]=rows[i][digit]=blocks[i/3][j/3][digit]=true;
board[i][j]= (char)(digit+'1');
dfs(board, step+1);
cols[j][digit]=rows[i][digit]=blocks[i/3][j/3][digit]=false;
}
}
}
}
leetcode41
- 缺失的第一个正数
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
进阶:你可以实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案吗?
示例 1:
输入:nums = [1,2,0]
输出:3
示例 2:
输入:nums = [3,4,-1,1]
输出:2
示例 3:
输入:nums = [7,8,9,11,12]
输出:1
提示:
0 <= nums.length <= 300
-231 <= nums[i] <= 231 - 1
package leetcode;
import utils.ArrayUtils;
public class l41 {
public static int firstMissingPositive(int[] nums) {
int N = nums.length + 1;
for (int i = 1; i <= nums.length; i++) {
if (nums[i - 1] <= 0) nums[i - 1] = N;
}
ArrayUtils.printArray(nums);
for (int i = 1; i <= nums.length; i++) {
int idx = Math.abs(nums[i - 1]);
if (idx > 0 && idx < N) {
nums[idx - 1] = -Math.abs(nums[idx - 1]);
}
}
ArrayUtils.printArray(nums);
for (int i = 1; i <= nums.length; i++) {
if (nums[i - 1] > 0) return i;
}
return nums.length + 1;
}
public static void main(String[] args) {
int[] nums = {3, 4, -1, 1};
// int[] nums = {1, 2, 0};
ArrayUtils.printArray(nums);
int res = firstMissingPositive(nums);
System.out.println(res);
}
}
leetcode42 接雨水
给定 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
leetcode44
给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。
'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/wildcard-matching
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
package leetcode;
import javafx.scene.effect.DisplacementMap;
public class l44 {
public static boolean isMatch(String s, String p) {
//s = "adceb"
//p = "*a*b"
char[] sChars = s.toCharArray();
char[] pChars = p.toCharArray();
boolean[][] m = new boolean[sChars.length + 1][pChars.length + 1];
m[0][0] = true;
for (int i = 1; i <= p.length() && pChars[i - 1] == '*'; i++) {
m[0][i] = true;
}
for (int i = 1; i <= sChars.length; i++) {
for (int j = 1; j <= pChars.length; j++) {
if (pChars[j - 1] == '*') {
m[i][j] |= m[i][j - 1];
m[i][j] |= m[i - 1][j];
} else if (pChars[j - 1] == '?' || sChars[i - 1] == pChars[j - 1]) {
m[i][j] |= m[i - 1][j - 1];
}
}
}
return m[sChars.length][pChars.length];
}
public static void main(String[] args) {
String s = "adceb";
// String p = "*a*b";
String p = "a*c?b";
System.out.println(isMatch(s, p));
}
}