Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 168 additions & 0 deletions Week_01/id_25/LeetCode_24_025.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package com.mootal.algo.day8_24;

/**
* Medium
* (注解文档查看快捷键 选中类名或方法名 按ctrl + Q)
* <p>
* 思维全过程记录方案:<p>
* 1 背基础结构和算法 | 记录在课程笔记<p>
* 2 看题 -> 悟题 思考过程 | 记录在wiki<p>
* 3 悟题 -> 写题 实现难点 | 记录在代码注解<p>
* 4 写题 -> 优化 多种解法 | 记录在leetcode提交
* <p>
* 问题:
* Given a linked list, swap every two adjacent nodes and return its head.
* You may not modify the values in the list's nodes, only nodes itself may be changed.
* 1->2->3->4 | 2->1->4->3
* <p>
* 题解方案topics:
* linked list
*
* @author li tong
* @date 2019/6/10 9:41
* @see Object
* @since 1.0
*/
public class SwapNodes24 {

private static class ListNode {
int val;

ListNode next;

ListNode(int x) {
val = x;
}

@Override
public String toString() {
return "{" + val +
", next=" + next +
'}';
}
}

public static void main(String[] args) {
ListNode a = new ListNode(1);
ListNode b = new ListNode(2);
ListNode c = new ListNode(3);
ListNode d = new ListNode(4);
a.next = b;
b.next = c;
c.next = d;
// System.out.println(swapListRecursive(a));
// understandSwapListRecursive(a);
System.out.println(swapPairs(a));
// System.out.println(swapPairs2(a));
}

/**
* 解法1 递归法<p>
* 看题解,主干思路:<p>
* &nbsp;&nbsp; 定义后序二步节点 找到返回方程<p>
* 自己学习 思考 实践时的难点(难点是如何突破的见wiki):<p>
* &nbsp;&nbsp; 如何找到返回方程 把单链表反转递归法又理解了一遍
*
* @param head
* @return
*/
public static ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
System.out.println();
return head;
}
ListNode after = head.next;
// 1 难点1 定义后序二步节点
ListNode nextTwo = after.next;
System.out.println(head + "就位,交代去程工作后," + head.val + "睡眠," + nextTwo + "进入到下一层");
ListNode back = swapPairs(nextTwo);
System.out.println("after=" + after + "返回到上一层,head=" + head + "唤醒,开始第一步:before指向back=" + back);
// 2 难点2 谁指向谁?
head.next = back;
System.out.println("第一步完成后,head=" + head + ",开始第二步:after" + after + "指向before");
// 3 难点3
after.next = head;
System.out.println("第二步完成后,after=" + after);
System.out.println();
// 4 难点4 返回什么?back 还是 after?
return after;
}

/**
* 解法2 遍历法<p>
* 看题解,主干思路:<p>
* &nbsp;&nbsp; 关键是要理解两步两步走<p>
* 自己学习 思考 实践时的难点(难点是如何突破的见wiki):<p>
* &nbsp;&nbsp; 想不到定义两个Node
*
* @param head
* @return
*/
public static ListNode swapPairs2(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = new ListNode(0);
newHead.next = head;
ListNode temp = newHead;
ListNode one = null;
ListNode two = null;
// {dummy->1->2->3->4->null}
while (temp.next != null && temp.next.next != null) {
// one -> 1
one = temp.next;
// two -> 2
two = temp.next.next;
// 1-> = 2.next = 3;
one.next = two.next;
// 2-> = 1
two.next = one;
// now newHead should point to 2
// if the below is not done newHead->1;
temp.next = two;
// temp was pointing to newHead
// temp->1
temp = one;
// now { dummy->2->1->3->4 }
}
return newHead.next;
}

/**
* !重要 完整笔记 自己理解递归方式链表反转
* 4->3->2->1
*
* @param before
* @return
*/
public static ListNode understandSwapListRecursive(ListNode before) {
if (before == null || before.next == null) {
System.out.println("最底层的世界空无一物," + before + "返回");
System.out.println();
return before;
}
ListNode after = before.next;
System.out.println("before=" + before + "就位,交代去程工作后,before=" + before.val + "睡眠,after=" + after + "进入到下一层");
ListNode back = understandSwapListRecursive(after);
System.out.println("back=" + back + "返回到上一层,before=" + before + "唤醒,开始第一步:before指向null");
/**
* 回归这里是难点
* 第一次失败 back.next = before; before.next = null; 第二次失败 before.next = null; back.next = before;
* 模板中这里不写,也能正常执行,先调试看看
*/
before.next = null;
System.out.println("第一步完成后,before=" + before + ",开始第二步:after" + after + "指向before");
after.next = before;
System.out.println("第二步完成后,after=" + after + ",back=" + back);
System.out.println();
return back;
}

public static void print(ListNode n) {
while (n != null) {
System.out.print(n.val);
n = n.next;
}
}

}
178 changes: 178 additions & 0 deletions Week_01/id_25/LeetCode_72_025.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package com.mootal.algo.day9_72;

/**
* Hard
* (注解文档查看快捷键 选中类名或方法名 按ctrl + Q)
* <p>
* 思维全过程记录方案:<p>
* 1 背基础结构和算法 | 记录在课程笔记<p>
* 2 看题 -> 悟题 思考过程 | 记录在wiki<p>
* 3 悟题 -> 写题 实现难点 | 记录在代码注解<p>
* 4 写题 -> 优化 多种解法 | 记录在leetcode提交
* <p>
* 问题:
* Given two words word1 and word2,
* find the minimum number of operations required to convert word1 to word2.
* <p>
* 题解方案topics:
* string、dp
*
* @author li tong
* @date 2019/6/11 10:06
* @see Object
* @since 1.0
*/
public class EditDistance72 {

public static void main(String[] args) {
// String word1 = "abc", word2 = "abc";
// String word1 = "horse", word2 = "rose";
String word1 = "rose", word2 = "horse";
System.out.println(minDistance(word1, word2));
System.out.println(minDistanceDP(word1, word2));
}

/**
* 递归解法 <p>
* 自己思考结合题解提示,主干思路:<p>
* &nbsp;&nbsp;1.先过一遍所有可能的解决方案 找到递归思路 2 用mem优化<p>
* 自己学习 思考 实践时的难点(难点是如何突破的见wiki):<p>
* &nbsp;&nbsp;1 看题解思路 自己尝试实现代码 写出相似度50% 再看答案
* &nbsp;&nbsp;2 边界条件处理
* &nbsp;&nbsp;3 多种路径组合出正确的递归写法
* &nbsp;&nbsp;4 如何合并到最终结果<p>
*
* @param word1
* @param word2
* @return
*/
public static int minDistance(String word1, String word2) {
char[] w1 = word1.toCharArray();
char[] w2 = word2.toCharArray();
int l1 = w1.length, l2 = w2.length;
int[][] mem = new int[l1][l2];
// return help(0, w1, 0, w2, mem);
return helpWithMem(0, w1, 0, w2, mem);
}

private static int help(int i, char[] w1, int j, char[] w2, int[][] mem) {
int insertCnt, deleteCnt, replaceCnt;
if (i == w1.length) {
// 长短不一致的情况 例如 rose -> horse
// 这里自己实现起来很困难 很难想到
return w2.length - j;
}
if (j == w2.length) {
// 长短不一致的情况 例如 horse -> rose
// 这里自己实现起来很困难 很难想到
return w1.length - i;
}
int res = 0;
if (w1[i] == w2[j]) {
// 直接return
// System.out.println("i=" + i);
res = help(i + 1, w1, j + 1, w2, mem);
// System.out.println("i=" + i);
return res;
} else {
deleteCnt = help(i + 1, w1, j, w2, mem);
System.out.println(deleteCnt);
insertCnt = help(i, w1, j + 1, w2, mem);
System.out.println(insertCnt);
replaceCnt = help(i + 1, w1, j + 1, w2, mem);
System.out.println(replaceCnt);
// 这里很难想到是取三者的最小值,还要加1是什么意思
res = Math.min(insertCnt, Math.min(deleteCnt, replaceCnt)) + 1;
// 自己写的代码 意思接近了
// if (w1[i + 1] == w2[j]) {
// i = i + 1;
// help(i + 1, w1, j, w2);
// deleteCnt++;
// } else if (w1[i] == w2[j + 1]) {
// j = j + 1;
// help(i, w1, j, w2);
// insertCnt++;
// } else {
// i = i + 1;
// j = j + 1;
// help(i, w1, j, w2);
// replaceCnt++;
// }
}
return res;
}

private static int helpWithMem(int i, char[] w1, int j, char[] w2, int[][] mem) {
int insertCnt, deleteCnt, replaceCnt;
if (i == w1.length) {
return w2.length - j;
}
if (j == w2.length) {
return w1.length - i;
}
if (mem[i][j] > 0) {
return mem[i][j];
}
int res = 0;
if (w1[i] == w2[j]) {
// System.out.println("i=" + i);
res = helpWithMem(i + 1, w1, j + 1, w2, mem);
// System.out.println("i=" + i);
return res;
} else {
deleteCnt = helpWithMem(i + 1, w1, j, w2, mem);
// System.out.println(deleteCnt);
insertCnt = helpWithMem(i, w1, j + 1, w2, mem);
// System.out.println(insertCnt);
replaceCnt = helpWithMem(i + 1, w1, j + 1, w2, mem);
// System.out.println(replaceCnt);
mem[i][j] = Math.min(insertCnt, Math.min(deleteCnt, replaceCnt)) + 1;
}
return mem[i][j];
}

/**
* DP解法 <p>
* 看题解,主干思路:<p>
* &nbsp;&nbsp; dp[i][j] 表示从 word1 的前i个字符转换到 word2 的前j个字符所需要的步骤<p>
* 自己学习 思考 实践时的难点(难点是如何突破的见wiki):<p>
* &nbsp;&nbsp;找出状态转移方程 思路:手写例子 简化变量
* DP特点
* 1 求极值
* 2 子问题最优解
* 3 dp和递归不同的是 dp是循环 递归是栈
* 4 dp倾向于倒序<p>
* . Ø a b c d<p>
* Ø 0 1 2 3 4<p>
* b 1 1 1 2 3<p>
* b 2 2 1 2 3<p>
* c 3 3 2 1 2<p>
*
* @param word1
* @param word2
* @return
*/
public static int minDistanceDP(String word1, String word2) {
char[] w1 = word1.toCharArray();
char[] w2 = word2.toCharArray();
int l1 = w1.length, l2 = w2.length;
int[][] dp = new int[l1 + 1][l2 + 1];
for (int i = 0; i <= l1; ++i) {
dp[i][0] = i;
}
for (int i = 0; i <= l2; ++i) {
dp[0][i] = i;
}
for (int i = 1; i <= l1; ++i) {
for (int j = 1; j <= l2; ++j) {
if (w1[i - 1] == w2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;
}
}
}
return dp[l1][l2];
}

}
Loading