昨天写了草稿,忘了发,今天补上。
今天是记录leetcode刷题的第九天,由于最近工作较多,刷题的速度略有下降。
今天得题目是最长公共子串、两链表的公共节点、链表相加。其中求最长公共子串是一道动态规划的题,但是相对来说还算可以。
最长公共子串
题目要求如下
给定两个字符串str1和str2,输出两个字符串的最长公共子串
题目保证str1和str2的最长公共子串存在且唯一。
正常思路就是暴力匹配法,两个指针i,j分别指向两个字符串的开始位置,此时两指针指向的字符对比,结果无非就是相等或不等,我们假设dp[i][j]表示当前指针指向的位置的字符的最大公共子串的长度
- 相等时,参照动态规划的思想,此时的值一定跟之前的值有关系,所以略加思考可以得出
- 不相等时,那么此时的dp[i][j]就为0
有了如上公式可以动手写代码了
代码如下
/**
* longest common substring
*
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @return string字符串
*/
public String getLcs(String str1, String str2) {
// KMP算法,求较短字符串的next数组
int len1 = str1.length();
int len2 = str2.length();
int[][] dp = new int[len1 + 1][len2 + 1];
int maxLastIndex = 0, maxLength = 0;
for (int i = 0; i < len1; i++) {
for (int j = 0; j < len2; j++) {
if (str1.charAt(i) == str2.charAt(j)) {
dp[i + 1][j + 1] = dp[i][j] + 1;
if (dp[i + 1][j + 1] > maxLength) {
maxLength = dp[i + 1][j + 1];
maxLastIndex = i;
}
} else {
dp[i + 1][j + 1] = 0;
}
}
}
return str1.substring(maxLastIndex - maxLength + 1, maxLastIndex + 1);
}
两链表的公共节点
题目要求如下
输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
思路如下
其实找链表的公共节点还是很简单的题目,首先我们需要明确,两链表节点相等是建立在其地址相等,不单单是其节点的值相等的。
那么如何找到两链表的公共节点呢?
方法有很多,如下
- 栈
- hash
- 双指针,长链表先行,然后与短链表同行,
代码如下
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
// 这里使用双指针,先求出两个链表的长度,让长的先走
int size1 = getSize(pHead1);
int size2 = getSize(pHead2);
int num = size1 > size2 ? size1 - size2 : size2 - size1;
if(size1 > size2) {
while(num-->0){
pHead1 = pHead1.next;
}
}else {
while(num-->0){
pHead2 = pHead2.next;
}
}
while(pHead1 != pHead2) {
pHead1 = pHead1.next;
pHead2 = pHead2.next;
}
return pHead1;
}
public int getSize(ListNode node) {
int size = 0;
while (node != null) {
size++;
node = node.next;
}
return size;
}
链表相加
题目要求如下
假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。
给定两个这种链表,请生成代表两个整数相加值的结果链表。
数据范围:0≤n,m≤1000000,链表任意值 0≤val≤9
要求:空间复杂度 O(n),时间复杂度 O(n)
思路如下
这个题跟上一题解法类似,难点在于单向链表只能从前往后遍历,但是我们需要从后往前相加,一旦我们遇到类似的问题,我们就可以使用栈来解决问题,所以这个难点也算不上难点啦。
代码如下
public ListNode addInList(ListNode head1, ListNode head2) {
// 栈
Stack<Integer> stack1 = new Stack<>();
Stack<Integer> stack2 = new Stack<>();
Stack<Integer> stack3 = new Stack<>();
while (head1 != null) {
stack1.push(head1.val);
head1 = head1.next;
}
while (head2 != null) {
stack2.push(head2.val);
head2 = head2.next;
}
// 进位
int carry = 0;
while (!stack1.isEmpty() || !stack2.isEmpty()) {
// 求和
int sum = carry;
if (!stack1.isEmpty()) {
sum += stack1.pop();
}
if (!stack2.isEmpty()) {
sum += stack2.pop();
}
stack3.add(sum % 10);
carry = sum / 10;
}
if(carry > 0){
stack3.add(carry);
}
ListNode newHead = new ListNode(0);
ListNode tmp = newHead;
while (!stack3.isEmpty()) {
tmp.next = new ListNode(stack3.pop());
tmp = tmp.next;
}
return newHead.next;
}
static class ListNode {
int val;
ListNode next = null;
public ListNode(int x) {
val = x;
}
}