人生不像做饭,不能等万事俱备了才下锅
目录
跳台阶
题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
class Solution {
public://循环
int jumpFloor(int number) {
int pos[number];//possibility
pos[0] = 1;
pos[1] = 2;
for (int i = 2; i < number; i++)
pos[i] = pos[i-1] + pos[i-2];
return pos[number-1];
}
};
class Solution {
public://迭代
int jumpFloor(int number) {
return jump(number);
}
int jump(int number)
{
if (number == 1)
return 1;
if (number == 2)
return 2;
return jump(number - 1) + jump(number - 2);
}
};
用两个栈实现队列
题目:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
class Solution
{
public:
void push(int node) {
while (!stack1.empty())
{
stack2.push(stack1.top());
stack1.pop();
}
stack1.push(node);
while (!stack2.empty())
{
stack1.push(stack2.top());
stack2.pop();
}
}
int pop() {
int node = stack1.top();
stack1.pop();
return node;
}
private:
stack<int> stack1;
stack<int> stack2;
};
子数组的最大累加问题
题目:给定一个数组arr,返回子数组的最大累加和 例如,arr = [1, -2, 3, 5, -2, 6, -1],所有子数组中,[3, 5, -2, 6]可以累加出最大的和12,所以返回12. 题目保证没有全为负数的数据
[要求] 时间复杂度为O(n),空间复杂度为O(1)
class Solution {
public:
int maxsumofSubarray(vector<int>& arr) {
int length = arr.size();
int total = 0, biggest = 0;
for (int i = 0; i < length; i++)
{
if (total <= 0)
total = arr[i];
else
total += arr[i];
if (total > biggest)
biggest = total;
}
return biggest;
}
};
字符串的最长无重复子字符串(剑指Offer 面试题48)
题目:给定一个数组arr,返回arr的最长无的重复子串的长度(无重复指的是所有数字都不相同)。
#include <unordered_map>
class Solution {
public:
int maxLength(vector<int>& arr) {
unordered_map<int, int> nums;
int length = 0, maxLength = 0;
for (int i = 0; i < arr.size(); i++)
{
if (nums.find(arr[i]) == nums.end())
length++;//如果该字符没有出现过则长度+1
else//如果出现过则考虑两种情况
{
int dis = i - nums.find(arr[i])->second;
if (dis > length)
length++;//该字符上次出现是在最长子串之前
else//该字符在当前最长子串之中
{
if (length > maxLength)
maxLength = length;//保存当前的最长字串长度
length = dis;//将该字符两次出现中间的字符串作为新的最长字串
}
}
nums[arr[i]] = i;
}
if (length > maxLength)//注意最后一次的最长字串
maxLength = length;
return maxLength;
}
};
合并有序链表
题目:将两个有序的链表合并为一个新链表,要求新的链表是通过拼接两个链表的节点来生成的,且合并后新链表依然有序。
输入:{1},{2}
输出:{1,2}
class Solution {
public://迭代
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
{
return merge(l1, l2);
}
ListNode* merge(ListNode* l1, ListNode* l2)
{
if (l1== nullptr)
return l2;
if (l2 == nullptr)
return l1;
ListNode* mergedNode = nullptr;
if (l1->val < l2->val)
{
mergedNode = l1;
mergedNode->next = merge(mergedNode->next, l2);//此时后面的已全部排序完毕,将选出的结点与之后的结点相连
}
else
{
mergedNode = l2;
mergedNode->next = merge(l1, mergedNode->next);
}
return mergedNode;
}
};
class Solution {
public://循环
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == nullptr)
return l2;
if (l2 == nullptr)
return l1;
ListNode* node = new ListNode(0), *result = node, *node1 = l1, *node2 = l2;
while (node1 != nullptr && node2 != nullptr)
{
if (node1->val < node2->val)
{
node->next = node1;
node = node1;
node1 = node1->next;
}
else
{
node->next = node2;
node = node2;
node2= node2->next;
}
}
if (node1 == nullptr)//注意未遍历完的结点
node->next = node2;
else if (node2 == nullptr)
node->next = node1;
return result->next;
}
};
寻找第K大
题目:有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数。
给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在。
输入:[1,3,5,2,2],5,3
输出:2
class Solution {
public://注意是第K大,也就是从大到小排序,注意边界条件
int findKth(vector<int> a, int n, int K) {
find(a, 0, n-1, K-1);
return a[K-1];
}
void find(vector<int>& a, int begin, int end, int K)
{
int index = Partition(a, begin, end);
int begin_1 = begin, end_1 = end;
while (K != index)
{
if (K > index)
{
begin_1 = index;
index = Partition(a, index+1, end_1);
}
else if (K < index)
{
end_1 = index;
index = Partition(a, begin_1, index-1);
}
}
}
int Partition(vector<int>& a, int begin, int end)
{
int value = a[begin];
while (begin < end)
{
while (a[end] <= value && begin < end)
end--;
a[begin] = a[end];
while (a[begin] >= value && begin < end)
begin++;
a[end] = a[begin];
}
a[end] = value;
return end;
}
};
合并两个有序的数组
题目:给出两个有序的整数数组A和B,请将数组B合并到数组A中,变成一个有序的数组
注意:可以假设A数组有足够的空间存放B数组的元素,A和B中初始的元素数目分别为m和n
class Solution {
public:
void merge(int A[], int m, int B[], int n) {
int p = m + n - 1;
n -= 1;
m -= 1;
while (m >= 0 && n >= 0)
{
if (A[m] > B[n])
A[p--] = A[m--];
else
A[p--] = B[n--];
}
if (m < 0)
while (n >= 0)
A[p--] = B[n--];
}
};
删除链表的倒数第 n 个结点
题目: 给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针 例如,给出的链表为:1→2→3→4→5,n = 2 删除了链表的倒数第 n 个节点之后,链表变为1→2→3→5
备注:题目保证 n 一定是有效的,请给出请给出时间复杂度为O(n)的算法
思路:设置两个指针,同时指向头结点,快的先走n步,当块的指针指向空指针时慢的指针正好指向倒数第n个结点
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if (head == nullptr)
return nullptr;
ListNode *low = head, *fast = head;
while (n-- >= 0)//此处的条件为>=0,也就是慢的指针会留在倒数第n+1个结点
{
if (fast == nullptr)//需要考虑删除的是头结点的情况,此时直接返回头结点的下一结点
return head->next;
fast = fast->next;
}
while (fast != nullptr)
{
fast = fast->next;
low = low->next;
}
low->next = low->next->next;
return head;
}
};
大数加法
题目:以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回。(字符串长度不大于100000,保证字符串仅由’0’~'9’这10种字符组成)
例如:输入:“1”,“99” ,输出:“100”
class Solution {
public:
string solve(string s, string t) {
if (s.length() == 0)
return t;
else if (t.length() == 0)
return s;
int m = s.size()-1, n = t.size()-1, total = 0;
string result;
while (m >= 0 || n >= 0 || total)
{
if (m >= 0)
total += s[m--] - '0';
if (n >= 0)
total += t[n--] - '0';
result = to_string(total%10) + result;
total /= 10;
}
return result;
}
};
最长公共子串
题目:给定两个字符串str1和str2,输出两个字符串的最长公共子串,题目保证str1和str2的最长公共子串存在且唯一。
例如:输入:“1AB2345CD”,“12345EF” ,输出:“2345”
思路:最直接的方法,遍历寻找最长公共子串,代码如下:
class Solution {
public:
string LCS(string str1, string str2) {
if (str1.size() == 0 || str2.size() == 0)
return "";
if (str1 == str2)
return str1;
if (str1.size() > str2.size())
swap(str1, str2);
int length1 = str1.size(), length2 = str2.size();
string str, result;
for (int i = 0; i < length1; i++)
{
int j = 0, m = i;
while (j < length2 && m < length1)
{
if (str1[m] == str2[j])
{
str += str2[j];
j++;
m++;
}
else
{
if (str.size() > result.size())
result = str;
str.clear();
j++;
m = i;
}
}
}
return result;
}
};
思路:动态规划,与序列比对算法Smith-Waterman算法类似,构建打分矩阵,然后回溯,代码如下:
class Solution {
public:
string LCS(string str1, string str2) {
if (str1.size() == 0 || str2.size() == 0)
return "";
if (str1 == str2)
return str1;
int len1 = str1.size() + 1, len2 = str2.size() + 1;
int* matrix = new int[len1 * len2]{ 0 };
int maxLength = 0, record[2] = { 0 };
for (int i = 1; i < len1; i++)
{
for (int j = 1; j < len2; j++)
{
if (str1[i - 1] == str2[j - 1])
{
matrix[i * len2 + j] = matrix[(i - 1) * len2 + j - 1] + 1;
if (matrix[i * len2 + j] > maxLength)
{
maxLength = matrix[i * len2 + j];
record[0] = i - 1;
record[1] = j - 1;
}
}
}
}
int m = record[0], n = record[1];
string result;
while (str1[m] == str2[n])
{
result = str1[m] + result;;
m--;
n--;
}
return result;
}
};
两个链表的第一个公共结点
题目:输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
思路:遍历第一个链表,对每个结点遍历第二个链表,直至找到公共结点或者没有,时间复杂度O(n)
,代码略;另一种思路代码如下:
分析:两种情况,如果长度相同,那么直接找到共同结点,或者没有共同结点,同时为nullptr
,此时while
循环结束;或者长度不一样,当一个链表先走到末尾时,此时两个链表之间的距离就是二者的长度差,将指针指向另一个链表的头指针(更长的那一个,还没有走完),当另一个链表也走完时,将指针指向较短链表的头指针,此时相当于两个链表长度一致。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if (pHead1 == nullptr || pHead2 == nullptr)
return nullptr;
ListNode *p1 = pHead1, *p2 =pHead2;
while (p1 != p2)
{
p1 = (p1 == nullptr ? pHead2 : p1->next);
p2 = (p2 == nullptr ? pHead1 : p2->next);
}
return p1;
}
};
两个链表生成相加链表
题目:假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。给定两个这种链表,请生成代表两个整数相加值的结果链表。
例如:链表 1 为 9->3->7,链表 2 为 6->3,最后生成新的结果链表为1->0->0->0。也就是937+63=1000。
思路:遍历两个链表,将结点存入栈中,然后依次相加,采用头插法生成新链表。代码如下:
class Solution {
public:
ListNode* addInList(ListNode* head1, ListNode* head2) {
if (head1 == nullptr)
return head2;
if (head2 == nullptr)
return head1;
int state = 0, total = 0;
stack<ListNode*> stack1, stack2;
ListNode *node = nullptr, *nextNode = nullptr;
while (head1 != nullptr)
{
stack1.push(head1);
head1 = head1->next;
}
while (head2 != nullptr)
{
stack2.push(head2);
head2 = head2->next;
}
ListNode* newHead = new ListNode(1);
while (!stack1.empty() || !stack2.empty())
{
if (!stack1.empty())
{
total += stack1.top()->val;
stack1.pop();
}
if (!stack2.empty())
{
total += stack2.top()->val;
stack2.pop();
}
total += state;
node = new ListNode(total%10);
node->next = nextNode;
newHead->next = node;
nextNode = node;
state = total / 10;
total = 0;
}
return state == 1 ? newHead : newHead->next;
}
};