【每日一题】1764. 通过连接另一个数组的子数组得到一个数组
题目描述
给你一个长度为 n 的二维整数数组 groups ,同时给你一个整数数组 nums 。
你是否可以从 nums 中选出 n 个 不相交 的子数组,使得第 i 个子数组与 groups[i] (下标从 0 开始)完全相同,且如果 i > 0 ,那么第 (i-1) 个子数组在 nums 中出现的位置在第 i 个子数组前面。(也就是说,这些子数组在 nums 中出现的顺序需要与 groups 顺序相同)
如果你可以找出这样的 n 个子数组,请你返回 true ,否则返回 false 。
输入:groups = [[1,-1,-1],[3,-2,0]], nums = [1,-1,0,1,-1,-1,3,-2,0]
输出:true
解释:你可以分别在 nums 中选出第 0 个子数组 [1,-1,0,1,-1,-1,3,-2,0] 和第 1 个子数组 [1,-1,0,1,-1,-1,3,-2,0] 。
这两个子数组是不相交的,因为它们没有任何共同的元素。
题目解析
class Solution {
public boolean canChoose(int[][] groups, int[] nums) {
int i = 0;
// k指向nums,i指向groups的数组
for(int k = 0; k < nums.length && i < groups.length;){
//判断当前k指向的和i指向的是否相等
if(nums[k] == groups[i][0]){
if(check(nums, groups[i], k)){
// 判断group下一个数组
k += groups[i].length;
i++;
}else{
k++;
}
}else{
k++;
}
}
//如果groups数组判断完,则代表都可以找到
if(i == groups.length) return true;
return false;
}
public boolean check(int[] nums, int[] g, int k){
if(k + g.length > nums.length) return false;
for(int i = 0; i < g.length; i++){
if(nums[k + i] != g[i]) return false;
}
return true;
}
}
【leetcode hot 100】76. 最小覆盖子串
题目描述
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”
解释:最小覆盖子串 “BANC” 包含来自字符串 t 的 ‘A’、‘B’ 和 ‘C’。
题目解析
【滑动窗口】:该题需要找到子字符串,经典的滑动窗口题目,使用双指针left,right;
right不断向右扩张,直至left和right中包含的是可行解。
left不断向右收缩,直至left和right中包含的不是可行解。
【哈希表】:将t中的字符及其个数使用哈希表来保存。
【count】:用来判断目前子字符串是否是可行解
class Solution {
public String minWindow(String s, String t) {
if(s.length() < t.length()) return "";
//哈希表,记录t中包含的字符,如果为正,代表目前子字符串不是可行解,如果某一个字符为负,则说明字符串有冗余
int[] record = new int[128];
for(char c : t.toCharArray()){
record[c]++;
}
// count用来记录 目前的子字符串是不是可行解
int count = t.length();
int min = Integer.MAX_VALUE;
int left = 0, right = 0;
int min_left = 0;
for(; right < s.length(); right++){
//判断目前的字符是不是我们需要的
if(record[s.charAt(right)] > 0){
count--;
}
record[s.charAt(right)]--;
//如果目前子字符串已经满足要求,则收缩left
while(left <= right && count == 0){
if(min > (right - left + 1)){
min_left = left;
min = right - left + 1;
}
record[s.charAt(left)]++;
if(record[s.charAt(left)] > 0){
count++;
}
left++;
}
}
if(min == Integer.MAX_VALUE) return "";
return s.substring(min_left, min_left + min);
}
}
【代码随想录】24. 两两交换链表中的节点
题目描述
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。
题目解析
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummyHead = new ListNode(0, head);
// 单数与偶数交换
ListNode pre = dummyHead; //上一个节点
ListNode cur = head; //目前的节点
int index = 0;
while(cur != null){
// 每次改变两个 cur为第一个 cur.next为第二个
if(cur.next == null){
pre.next = cur;
break;
}
ListNode temp = cur.next.next;
pre.next = cur.next;
cur.next.next = cur;
cur.next = temp;
pre = cur;
cur = temp;
}
return dummyHead.next;
}
}