- 反转链表 (小米开发)
#include <bits/stdc++.h>
using namespace std;
struct ListNode{
int val;
struct ListNode *next;
ListNode(int x):
val(x), next(nullptr){}
};
ListNode* Reverse(ListNode *head){
if(!head || !head->next) return head;
ListNode *pre = nullptr, *cur = head;
while(cur){
auto next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
int main(){
auto p1 = new ListNode(1);
auto p2 = new ListNode(2);
auto p3 = new ListNode(3);
auto p4 = new ListNode(4);
auto p5 = new ListNode(5);
p1->next = p2;
p2->next = p3;
p3->next = p4;
p4->next = p5;
p5->next = NULL;
auto head = Reverse(p1);
for(auto p = head; p; p = p->next)
cout << p->val << ' ';
return 0;
}
补充: 输入数组
1). 需要输入数组长度
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
struct ListNode{
int val;
struct ListNode *next;
ListNode(int x):
val(x), next(nullptr){}
};
ListNode* Reverse(ListNode *head){
if(!head || !head->next) return head;
ListNode *pre = nullptr, *cur = head;
while(cur){
auto next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
int main(){
int n, a[N];
cin >> n;
ListNode *dummy = new ListNode(-1);
dummy->next = NULL;
ListNode *pre = dummy;
for(int i = 0; i < n; i++){
cin >> a[i];
ListNode *p = new ListNode(a[i]);
p->next = NULL;
pre->next = p;
pre = p;
}
auto head = Reverse(dummy->next);
for(auto p = head; p; p = p->next)
cout << p->val << ' ';
return 0;
}
2). 不需要输入数组长度
#include <bits/stdc++.h>
using namespace std;
struct ListNode{
int val;
struct ListNode *next;
ListNode(int x):
val(x), next(nullptr){}
};
ListNode* Reverse(ListNode *head){
if(!head || !head->next) return head;
ListNode *pre = nullptr, *cur = head;
while(cur){
auto next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
int main(){
vector<int> nums;
int x;
while(cin >> x){
nums.push_back(x);
if (cin.get() == '\n')//如果是回车符则跳出循环
break;
}
ListNode *dummy = new ListNode(-1);
dummy->next = NULL;
ListNode *pre = dummy;
for(int i = 0; i < nums.size(); i++){
ListNode *p = new ListNode(nums[i]);
p->next = NULL;
pre->next = p;
pre = p;
}
auto head = Reverse(dummy->next);
for(auto p = head; p; p = p->next)
cout << p->val << ' ';
return 0;
}
扩展:合并两个有序链表
#include <bits/stdc++.h>
using namespace std;
struct ListNode{
int val;
struct ListNode *next;
ListNode(int x):
val(x), next(nullptr){}
};
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode *dummy = new ListNode(0);
ListNode *cur = dummy;
while (l1 != NULL && l2 != NULL) {
if (l1 -> val < l2 -> val) {
cur -> next = l1;
l1 = l1 -> next;
}
else {
cur -> next = l2;
l2 = l2 -> next;
}
cur = cur -> next;
}
cur -> next = (l1 != NULL ? l1 : l2);
return dummy -> next;
}
ListNode* create(vector<int> &nums){
ListNode *dummy = new ListNode(-1);
dummy->next = NULL;
ListNode *pre = dummy;
for(int i = 0; i < nums.size(); i++){
ListNode *p = new ListNode(nums[i]);
p->next = NULL;
pre->next = p;
pre = p;
}
return dummy->next;
}
int main(){
vector<int> nums1;
vector<int> nums2;
int x;
while(cin >> x){
nums1.push_back(x);
if (cin.get() == '\n')//如果是回车符则跳出循环
break;
}
int t;
while(cin >> t){
nums2.push_back(t);
if (cin.get() == '\n')//如果是回车符则跳出循环
break;
}
ListNode *l1 = create(nums1);
ListNode *l2 = create(nums2);
auto head = merge(l1, l2);
for(auto p = head; p; p = p->next)
cout << p->val << ' ';
return 0;
}
1 6 12 18
3 5 9 20
=> 1 3 5 6 9 12 18 20
- 无序数组,二分查找(字节客户端)
动态二维数组的定义:
vector<vector<int>> a(nums.size(),vector<int>(2));
返回行数:a.size()
返回列数:a[0].size()
用二维数组保存原数组的值和下标
#include <bits/stdc++.h>
using namespace std;
int main(){
vector<int> nums = {3,1,2,5,6,4,4};
int k = 3;
vector<vector<int>> a(nums.size(),vector<int>(2));
for(int i = 0; i < nums.size(); i++){
a[i][0] = nums[i];
a[i][1] = i;
}
sort(a.begin(), a.end());
int l = 0, r = a.size()-1;
while(l < r){
int mid = l + r >> 1;
if(a[mid][0] < k) l = mid+1;
else r = mid;
}
cout << a[l][1]+1;
return 0;
}
- 判断给定的链表中是否有环
扩展:
你能给出空间复杂度的解法么?
思路: 参考链表环的第一个入口结点,快慢指针第一次能相遇,一定有环
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(!head || !head->next) return 0;
auto i = head, j = head;
while(i && j){
i = i->next;
j = j->next;
if(j) j = j->next;
if(i == j){
return 1;
}
}
return 0;
}
};
3-2 环的入口结点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(!head || !head->next) return 0;
auto i = head, j = head;
while(i && j){
i = i->next;
j = j->next;
if(j) j = j->next;
if(i == j){
i = head;
while(i != j){
i = i->next;
j = j->next;
}
return i;
}
}
return NULL;
}
};
- 合并两个有序链表
将两个有序的链表合并为一个新链表,要求新的链表是通过拼接两个链表的节点来生成的。
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param l1 ListNode类
* @param l2 ListNode类
* @return ListNode类
*/
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
// write code here
if(!l1) return l2;
if(!l2) return l1;
auto dummy = new ListNode(-1), tail = dummy;
while(l1 && l2){
if(l1->val < l2->val) tail = tail->next = l1, l1=l1->next;
else tail = tail->next = l2, l2=l2->next;
}
if(l1) tail->next = l1;
if(l2) tail->next = l2;
return dummy->next;
}
};
- 寻找第K大
有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数。
给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在。
测试样例:
[1,3,5,2,2],5,3
返回:2
class Finder {
public:
int q_sort(vector<int> q, int l, int r, int k){
if(l >= r) return q[l];
int i = l-1, j =r+1, x = q[l+r>>1];
while(i < j){
do i++; while(q[i] > x);
do j--; while(q[j] < x);
if(i < j) swap(q[i], q[j]);
}
if(j-l+1 >= k) return q_sort(q, l, j, k);
else return q_sort(q,j+1, r,k-(j-l+1));
}
int findKth(vector<int> a, int n, int K) {
// write code here
return q_sort(a, 0, n-1, K);
}
};
- 两个链表生成相加链表
假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。
给定两个这种链表,请生成代表两个整数相加值的结果链表。
例如:链表 1 为 9->3->7,链表 2 为 6->3,最后生成新的结果链表为 1->0->0->0。
示例1
输入
[9,3,7],[6,3]
输出
{1,0,0,0}
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head1 ListNode类
* @param head2 ListNode类
* @return ListNode类
*/
ListNode* Reverse(ListNode *head){
ListNode *pre = NULL, *cur = head;
while(cur){
auto next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
ListNode* addInList(ListNode* head1, ListNode* head2) {
// write code here
auto l1 = Reverse(head1);
auto l2 = Reverse(head2);
ListNode *dummy = new ListNode(-1), *cur = dummy; // dummy为虚拟头结点,cur指向和链表的尾结点
int t = 0; // 进位
while(l1 || l2 || t){ // 某一个链表不为空或进位不为0,一直做
if(l1) t += l1->val, l1 = l1->next;
if(l2) t += l2->val, l2 = l2->next;
cur->next = new ListNode(t % 10);
t /= 10;
cur = cur->next;
}
return Reverse(dummy->next); // 返回和链表真正的头结点
}
};
- 字符串转整数(字节开发)
class Solution {
public:
int myAtoi(string str) {
// 删掉空白字符
int k = 0;
while(k < str.size() && str[k] == ' ') k++;
if(k == str.size()) return 0; // 空白字符串
// 判断正负号,minus默认为正
int minus = 1;
if(str[k] == '-') minus = -1, k++;
else if(str[k] == '+') k++;
// 转换为整数
long long res = 0;
while(k < str.size() && str[k] >= '0' && str[k] <= '9'){
res = res * 10 + str[k] - '0';
k++;
if(res > INT_MAX) break; // 超出范围,终止
}
// 判断溢出
res *= minus;
if(res > INT_MAX) res = INT_MAX;
if(res < INT_MIN) res = INT_MIN;
return res;
}
};
- 摆动序列 leetcode 376 (字节测试)
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。
例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。
示例 1:
输入: [1,7,4,9,2,5]
输出: 6
解释: 整个序列均为摆动序列。
示例 2:
输入: [1,17,5,10,13,15,10,5,16,8]
输出: 7
解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。
示例 3:
输入: [1,2,3,4,5,6,7,8,9]
输出: 2