14、最长公共前缀

#include <iostream>
#include <string.h>
#include <vector>
using namespace std;
class Solution {
public:
string longestCommonPrefix(vector<string> &strs) {
string ans;
int Size = strs.size();
if (Size == 0) {
return ans;
}
int MinLen = strs.at(0).length();
for (int i = 0; i < Size; i++) {
if (strs.at(i).length() < MinLen) {
MinLen = strs.at(i).length();
}
}
if (MinLen == 0) {
return ans;
}
bool judge = 1;
for (int i = 0; i < MinLen; i++) {
char temp = strs.at(0).at(i);
for (int j = 1; j < Size; j++) {
if (strs.at(j).at(i) != temp) {
judge = 0;
break;
}
}
if (judge) {
ans.push_back(temp);
} else {
break;
}
}
return ans;
}
//*123/123 cases passed (0 ms)
//*Your runtime beats 100 % of cpp submissions
//*Your memory usage beats 76.45 % of cpp submissions (8.9 MB)
};

20、有效的括号

#include <iostream>
#include <stack> //https://blog.csdn.net/lhyer/article/details/47908063
#include <string.h>
using namespace std;
class Solution {
public:
bool judge(char ch1, char ch2) {
if (ch1 == '(' && ch2 == ')') {
return 1;
}
if (ch1 == '[' && ch2 == ']') {
return 1;
}
if (ch1 == '{' && ch2 == '}') {
return 1;
}
return 0;
}
bool isValid(string s) {
int len = s.length();
if (len == 0) {
return 1;
}
if (len == 1) {
return 0;
}
stack<char> st;
st.push(s[0]);
for (int i = 1; i < len; i++) {
if (st.empty()) {
st.push(s[i]);
} else {
if (judge(st.top(), s[i])) {
st.pop();
} else {
st.push(s[i]);
}
}
}
if (st.empty()) {
return 1;
} else {
return 0;
}
}
};
//*91/91 cases passed (0 ms)
//*Your runtime beats 100 % of cpp submissions
//*Your memory usage beats 26.67 % of cpp submissions (6.3 MB)
// TODO:有必要优化一下空间

21、合并两个有序链表

#include <iostream>
#include <stdlib.h>

using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};

class Solution {
public:
ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
ListNode l3;
ListNode *p3 = &l3;
while (l1 && l2) {
if (l1->val <= l2->val) {
p3->next = l1;
l1 = l1->next;
p3 = p3->next;
} else {
p3->next = l2;
l2 = l2->next;
p3 = p3->next;
}
}
p3->next = l1 ? l1 : l2;
return l3.next;
}
};
// 208/208 cases passed (12 ms)
// Your runtime beats 48.07 % of cpp submissions
// Your memory usage beats 99.03 % of cpp submissions (14.2 MB)

写完这道题,更加深刻地明白了链表排序的方法。

以下是学校《数据结构》上面写的排序函数:

void MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc) {
LinkList ptr;
LinkList pa = La->next;
LinkList pb = Lb->next; // pa、pb无头部的空节点
LinkList pc = La; //和上面不同,开头是对空结点的处理
Lc = La; // La的头结点作为Lc的头结点
while (pa && pb) { //需要比较的段
if (pa->data < pb->data) {
pc->next = pa;
pc = pa; //更新节点
pa = pa->next; // pa后移
} else if (pa->data > pb->data) {
pc->next = pb;
pc = pb;
pb = pb->next;
} else {
pc->next = pa; //多了一步删除重复数字的操作
pc = pa;
pa = pa->next;
ptr = pb;
pb = pb->next;
free(ptr);
}
}
pc->next = pa ? pa : pb; //插入剩余段
free(Lb);
}

可以看到,在真正的核心代码部分,我在LeetCode上写的如下:

p3->next = l1;
l1 = l1->next;
p3 = p3->next;

书上的:

pc->next = pb;
pc = pb;
pb = pb->next;

我承认两者就是一个意思,但是为什么后者一定要写成pc=pb?这完全曲解了代码的意思,相比之下p3 = p3->next就一目了然,直接表明移动到下一个。

26、删除有序数组中的重复项

#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int removeDuplicates(vector<int> &nums) {
int len = nums.size();
for (int i = 0; i < len - 1; i++) {
if (nums.at(i) == nums.at(i + 1)) {
for (int j = i; j < len - 1; j++) {
nums.at(j) = nums.at(j + 1);
}
i--;
len--;
}
}
return len;
}
//一遍过,可以!
// 161/161 cases passed (1648 ms)
//*应该是用了两个循环的问题,时间复杂度有点大了
// Your runtime beats 5.36 % of cpp submissions
// Your memory usage beats 57.44 % of cpp submissions (13.3 MB)
// TODO:优化这个代码
};