题目
lc725.分隔链表
lc326. 3的幂
lc430. 扁平化多级双向链表
lc583. 两个字符串的删除操作
lc371. 两整数之和
09-22 lc725.分隔链表
- 第一天开始每日一题,做个记录吧,也是让自己坚持下去
- 题意为按照k来将链表分成k份,任意两份长度不超过1
- 那么很显然,最长的区间长度,len/k + 1, 个数一共有len%k个 最短的len/k
- 代码如下,基本是优解
- 好久没写java了,手挺生的,敲挺慢的哈哈哈
class Solution {
//首先需要知道长度
//平均长度 len/k,则有len % k个是len/k +1的其余都是len/k
//然后进行分割
public ListNode[] splitListToParts(ListNode head, int k) {
//确定链表长度
int len = 0;
ListNode cur = head;
while(cur!=null){
cur = cur.next;
len++;
}
//计算平均长度
int avg = len/k;
int longer = len%k;//avg +1 的有这么多
//进行分割
cur = head;
ListNode[] res = new ListNode[k];
for(int i=0; i<k; i++){
ListNode newHead = splitHelp(cur,longer-->0?avg+1:avg);
res[i] = cur;
cur = newHead;
}
return res;
}
//截取k个长度的链表,返回新头部
private ListNode splitHelp(ListNode head, int k){
if(k==0||head==null) return head;
while(k>1){
head = head.next;
k--;
if(head==null) return head;
}
ListNode next = head.next;
head.next = null;
return next;
}
}
09-23 lc326. 3的幂
- 不让用迭代和递归
- 这题两个思路,一个是将正数的3的幂全部写出来,放到set中,然后对比就行
- 另一个思路是,写出最大的3的幂,用它来除。对于质数的幂,它的因子只可能是质数的幂
public boolean isPowerOfThree(int n) {
//n是0,直接false
//否则看看能不能被1162261467 整除
return n>0 && 1162261467%n==0;
}
09-24 lc430. 扁平化多级双向链表
- 这一题就是将多个链表进行合并成一个链表,而多个链表之间通过child指针来进行连接
- 遍历的逻辑是遇到child就走child,没有child就走next,如果为空,就返回让一次的child那里,继续走next
- 所以整体的逻辑可以用栈来进行表示,如果有child的节点,就把它的next放进栈里,(当然要进行判空)
- 这里的输入,写的非常的难懂,配的图片又小,有点不太开心,直接看图片就能懂,别看那个数组了,有点反人类
- 题还是非常简单的,一眼就能出思路,不过链表嘛,以及循环逻辑,还是稍微有一点点麻烦的
- 然后因为要返回一个链表,所以我就新建了节点,空间复杂度高一点,不然会很麻烦
class Solution {
//这边的这个输入没有什么问题,不用看这个
//然后就是感觉像是栈
//遍历链表,如果当前节点有child,就放入栈,访问child,如果没有就访问next,如果也没有next,就访问出栈的节点
//然后这个是要返回一个新的链表,所以直接复制一个好了
public Node flatten(Node head) {
Deque<Node> stack = new LinkedList<>();
Node cur = head;
Node newHead = new Node();
Node newCur = newHead;
while(cur!=null||!stack.isEmpty()){
if(cur==null) cur = stack.pop();
Node newNext = new Node(cur.val);
newCur.next = newNext;
newNext.prev = newCur;
newCur = newNext;
if(cur.child!=null){
if(cur.next!=null) stack.push(cur.next);
cur = cur.child;
}
else cur = cur.next;
}
//处理一下头部
if(head!=null) newHead.next.prev=null;
return newHead.next;
}
}
09-25 lc583. 两个字符串的删除操作
- 这是一个标准的双序列dp问题,难度较低
- 平板的键盘不太行,用起来太煎熬了,打算买个键盘
- f [ i ] [ j ] = w o r d 1 前 i 个 和 w o r d 2 前 j 个 相 同 的 步 骤 数 f[i][j]=word1前i个和word2前j个相同的步骤数 f[i][j]=word1前i个和word2前j个相同的步骤数
- 如果当前i字符和j字符相等,则 f [ i ] [ j ] = f [ i − 1 ] [ j − 1 ] f[i][j]=f[i-1][j-1] f[i][j]=f[i−1][j−1],如果不等,则就直接是 f [ i − 1 ] [ j ] + 1 , f [ i ] [ j − 1 ] + 1 f[i-1][j]+1, f[i][j-1]+1 f[i−1][j]+1,f[i][j−1]+1的最大值了。
- 总之就是把问题抛给上一个就可以了
- 代码比较简单明了,注意要初始化,别忘了就行,逻辑比较简单
class Solution {
public int minDistance(String word1, String word2) {
char[] w1 = word1.toCharArray();
char[] w2 = word2.toCharArray();
int m = w1.length, n = w2.length;
int[][] f = new int[m+1][n+1];
//初始条件:当i为0时,就为j,j为0时,就为i
for(int i=0; i<m+1; i++) f[i][0] = i;
for(int j=0; j<n+1; j++) f[0][j] = j;
for(int i=1; i<=m; i++){
for(int j=1; j<=n; j++){
if(w1[i-1]==w2[j-1]) f[i][j] = f[i-1][j-1];
else f[i][j] = Math.min(f[i-1][j],f[i][j-1])+1;
}
}
return f[m][n];
}
}
09-26 lc371. 两整数之和
- 不让用+,-
- 所以自然而然用位运算,
- 这里其实是可以用位运算来解决所有的加减法的,贴上个链接https://blog.csdn.net/ojshilu/article/details/11179911
- 递归加位运算
//每次递归都是: 不考虑进位加法结果 + 进位结果 》》》递归得出最终结果
public int getSum(int a, int b) {
if(b==0) return a;
int s = a^b;//不考虑进位的加情况
int c = (a&b)<<1;//这里是进位情况,左移一就到了该到的位置
return getSum(s,c);
}