文章目录
前言
1、交错字符串
2、移除链表元素
3、反转链表
4、反转链表||
5、赢得比赛需要的最少训练时长
6、给定行和列的和求可行矩阵
7、最大网络秩
8、统计中位数为 K 的子数组
一、交错字符串(力扣97)【动态规划】****
class Solution {
public boolean isInterleave(String s1, String s2, String s3) {
int ss1 = s1.length();
int ss2 = s2.length();
int ss3 = s3.length();
if(ss1+ss2!=ss3) return false;
boolean[][] dp = new boolean[ss1+1][ss2+1];
dp[0][0] = true;
//初始化
for(int i=1;i<=ss1 && s1.charAt(i-1)==s3.charAt(i-1);i++){
dp[i][0] = true;
}
for(int j=1;j<=ss2 && s2.charAt(j-1)==s3.charAt(j-1);j++){
dp[0][j] = true;
}
for(int i=1;i<=ss1;i++){
for(int j=1;j<=ss2;j++){
dp[i][j] = (dp[i-1][j] && s1.charAt(i-1)==s3.charAt(i+j-1)) || (dp[i][j-1]&& s2.charAt(j-1)==s3.charAt(i+j-1));
}
}
return dp[ss1][ss2];
}
}
二、移除链表元素(力扣203)
分析:
需要定义一个头节点!(为了方便操作,不需要单独处理头节点)
/**
* 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 removeElements(ListNode head, int val) {
if(head==null) return head;
ListNode p,pre;
//增加头节点
ListNode dummy = new ListNode(-1,head);
dummy.next = head;
pre = dummy;
p=pre.next;
while(p!=null){
if(p.val==val){
pre.next = p.next;
}
else{
pre = p;
}
p=pre.next;
}
return dummy.next;
}
}
三、反转链表(力扣206)
分析:
递归:
题解来源:大佬题解
/**
* 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 reverseList(ListNode head) {
if(head==null) return null;
if(head.next==null){
return head;
}
ListNode last = reverseList(head.next);
head.next.next = head;
head.next=null;
return last;
}
}
四、反转链表||(力扣92)
分析:
与上一题思路基本一致
/**
* 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 {
ListNode succesor = null;
public ListNode reverseBetween(ListNode head, int left, int right) {
if(left==1){
return reverseN(head,right);
}
head.next = reverseBetween(head.next,left-1,right-1);
return head;
}
public ListNode reverseN(ListNode head, int n) {
if(n==1) {
succesor = head.next;
return head;
}
ListNode last = reverseN(head.next,n-1);
head.next.next = head;
head.next = succesor;
return last;
}
}
每日一题day66:赢得比赛需要的最少训练时长(力扣2383)
模拟:
把过程顺下来
class Solution {
public int minNumberOfHours(int initialEnergy, int initialExperience, int[] energy, int[] experience) {
int hour = 0;
int ehour = 0;
int res = 0;
int sum = 0;
//精力值:
for(int i=0;i<energy.length;i++){
sum+=energy[i];
}
if(initialEnergy<=sum){
hour = sum-initialEnergy+1;
}
int trainingTime = 0;
//经验值:
for(int i=0;i<experience.length;i++){
if(initialExperience-experience[i]>0){
//可以打败 收获经验值即可
initialExperience += experience[i];
}else{
//打败不了 计算需要多长时间训练
ehour += experience[i] - initialExperience+1;
trainingTime = experience[i] - initialExperience+1;
//训练完后 初始值发生了变化 可以打败了
initialExperience += trainingTime + experience[i];
}
}
res = hour+ehour;
return res;
}
}
每日一题day67:给定行和列的和求可行矩阵【力扣1605】
**分析:**模拟过程即可
class Solution {
public int[][] restoreMatrix(int[] rowSum, int[] colSum) {
int m = rowSum.length;
int n = colSum.length;
int[][] res = new int[m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(rowSum[i]<=colSum[j]){
res[i][j] = rowSum[i];
colSum[j] = colSum[j]-rowSum[i];
rowSum[i] -= res[i][j];
}else{
res[i][j] = colSum[j];
rowSum[i] = rowSum[i]-colSum[j];
colSum[j] -= res[i][j];
}
}
}
return res;
}
}
每日一题day68:最大网络秩(力扣1615)
分析:
其实就是两个结点之间的度数之和
需要注意的是:
class Solution {
public int maximalNetworkRank(int n, int[][] roads) {
boolean[][] connect = new boolean[n][n];
int[] degree = new int[n]; //度数
for(int[] v:roads){ //一条无向边
connect[v[0]][v[1]]=true;
connect[v[1]][v[0]]=true;
degree[v[0]]++;
degree[v[1]]++;
}
int maxRank = 0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
int rank=degree[i]+degree[j]-(connect[i][j]==true?1:0);
maxRank = Math.max(maxRank,rank);
}
}
return maxRank;
}
}
每日一题day69:统计中位数为 K 的子数组(力扣2488)【前缀和+哈希表】
分析:
连续数组问题一定要想想前缀和!!!
class Solution {
public int countSubarrays(int[] nums, int k) {
//前缀和+哈希表
HashMap<Integer,Integer> map = new HashMap<>();
map.put(0,1);
int index =0;
//先找k在num数组中所在的位置
for(int i=0;i<nums.length;i++){
if(nums[i]==k)
index = i;
}
int preLeft =0;
int res =0;
//左边已经准备好了
for(int i=index-1;i>=0;i--){
preLeft+=nums[i]>k?-1:1;
map.put(preLeft,map.getOrDefault(preLeft,0)+1);
}
//开始计算右边
int preRight =0;
if(map.containsKey(0)){
res+=map.get(0);
}
if(map.containsKey(-1)){
res+=map.get(-1);
}
for(int i=index+1;i<nums.length;i++){
preRight+=nums[i]<k?-1:1;
if(map.containsKey(preRight)){
res+=map.get(preRight);
}
if(map.containsKey(preRight-1)){
res+=map.get(preRight-1);
}
}
return res;
}
}
注意:
计算左边map值时不是从左到右 ,而是需要从k值所在下标开始–一直到0