面试题 01.02. 判定是否互为字符重排
原题链接
思路 判断字符数量是否一致
class Solution {
public:
bool CheckPermutation(string s1, string s2) {
vector<int>a(256,0);
vector<int>b(256,0);
int len1 = s1.size();
int len2 = s2.size();
if (len1 != len2) return false;
for (int i = 0;i < len1;i++)
{
a[s1[i]]++;
b[s2[i]]++;
}
for (int i = 0;i < 256;i++)
{
if (a[i] != b[i])
return false;
}
return true;
}
};
面试题 01.03. URL化
原题链接
思路:遇到空格替换
class Solution {
public:
string replaceSpaces(string S, int length) {
string res = "";
int i = 0;
for (char c : S)
{
if (c == ' ')
res += "%20";
else
res += c;
i++;
if (i == length)
break;
}
return res;
}
};
面试题 01.04. 回文排列
原题链接
思路:map记录字符出现个数
class Solution {
public:
bool canPermutePalindrome(string s) {
unordered_map<char,int>m;
for (char c:s)
{
m[c]++;
}
int count = 0;
for (auto it : m)
{
if (it.second % 2 == 1)
count ++;
}
if (count <= 1)
return true;
else
return false;
}
};
面试题 01.05. 一次编辑
思路:分别从两个字符串的两边向中间匹配,一旦不一样就停止,这时剩下的first[i,j]first[i,j]和second[i,k]second[i,k]如果长度均小于等于1(注意临界条件)则结果为True,否则False。
class Solution {
public:
bool oneEditAway(string first, string second) {
if(first == second)
{
return true;
}
const int len1 = first.size();
const int len2 = second.size();
if (abs(len1 - len2) > 1)
{
return false;
}
int i = 0, j = len1 - 1, k = len2 - 1;
while (i < len1 && i < len2 && first[i] == second[i]){ // i从左至右扫描
++i;
}
while(j >= 0 && k >= 0 && first[j] == second[k]){ // j、k从右至左扫描
--j;
--k;
}
return j - i < 1 && k - i < 1;
}
};
面试题 01.06. 字符串压缩
class Solution {
public:
string compressString(string S) {
int len = S.size();
char ch = S[0];
int count = 1;
string ans = "";
for (int i = 1;i < len;i++)
{
if (ch == S[i])
{
count++;
}
else
{
ans += ch + to_string(count);
ch = S[i];
count = 1;
}
}
ans += ch + to_string(count);
return (ans.size() < S.size()) ? ans : S;
}
};
面试题 01.07. 旋转矩阵
思路:先水平翻转,在对角线翻转
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int rows = matrix.size();
if (rows == 0) return;
int cols = matrix[0].size();
//水平翻转
for (int i = 0; i < rows/2; i++)
{
for (int j = 0;j < cols; j++)
{
swap(matrix[i][j],matrix[rows - i - 1][j]);
}
}
//对角线翻转
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < i; j++)
{
swap(matrix[i][j],matrix[j][i]);
}
}
return;
}
};
面试题 01.08. 零矩阵
原题链接
思路:先标记后置0
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int rows = matrix.size();
if (rows == 0) return;
int cols = matrix[0].size();
vector<int>r(rows,1);
vector<int>c(cols,1);
for (int i = 0;i < rows;i++)
{
for (int j = 0;j < cols;j++)
{
if (matrix[i][j] == 0)
{
r[i] = 0;
c[j] = 0;
}
}
}
for (int i = 0;i < rows;i++)
{
if (r[i] == 0)
{
for (int j = 0;j < cols;j++)
{
matrix[i][j] = 0;
}
}
}
for (int j = 0;j < cols;j++)
{
if (c[j] == 0)
{
for (int i = 0;i < rows;i++)
{
matrix[i][j] = 0;
}
}
}
return;
}
};
面试题 01.09. 字符串轮转
class Solution {
public:
bool isFlipedString(string s1, string s2) {
int len1 = s1.size();
int len2 = s2.size();
if (len1 != len2) return false;
if (len1 == 0) return true;
for (int i = 0;i < len2;i++)
{
if (s1[i] == s2[0])
{
if ( (s1.substr(i) == s2.substr(0,len1 - i))
&& (s1.substr(0,i) == s2.substr(len1 - i)))
return true;
}
}
return false;
}
};
面试题 02.01. 移除重复节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeDuplicateNodes(ListNode* head) {
if (head == nullptr) return head;
ListNode *tmp = head;
unordered_map<int,int>m;
m[head->val] = 1;
while (tmp->next != nullptr)
{
if (m.count(tmp->next->val))
{
tmp->next = tmp->next->next;
}
else
{
m[tmp->next->val] = 1;
tmp = tmp->next;
}
}
return head;
}
};
面试题 02.02. 返回倒数第 k 个节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
int kthToLast(ListNode* head, int k) {
ListNode* slow = head;
ListNode* fast = head;
for (int i = 0; i < k; i++)
{
fast = fast->next;
}
while (fast)
{
slow = slow->next;
fast = fast->next;
}
return slow->val;
}
};
面试题 02.03. 删除中间节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
if (node == nullptr) return;
node->val = node->next->val;
node->next = node->next->next;
return;
}
};
面试题 02.04. 分割链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode* p1 = new ListNode(0);
ListNode* p2 = new ListNode(0);
ListNode* t1 = p1;
ListNode* t2 = p2;
while (head)
{
if (head->val < x)
{
t1->next = head;
t1 = t1->next;
}
else
{
t2->next = head;
t2 = t2->next;
}
head = head->next;
}
if (p2)
t1->next = p2->next;
t2->next = nullptr;
return p1->next;
}
};
面试题 02.05. 链表求和
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode(0);
ListNode* tmp = head;
int carry = 0;
while (l1 || l2 || carry)
{
int x = l1 ? l1->val : 0;
int y = l2 ? l2->val : 0;
int sum = x + y + carry;
carry = sum / 10;
sum = sum % 10;
tmp->next = new ListNode(sum);
tmp = tmp->next;
if (l1)
l1 = l1->next;
if (l2)
l2 = l2->next;
}
return head->next;
}
};
面试题 02.06. 回文链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
if (head == nullptr || head->next == nullptr) return true;
ListNode* fast = head->next;
ListNode* slow = head;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
}
ListNode *cur = slow->next;
ListNode *pre = nullptr;
ListNode *nxt = nullptr;
slow->next = nullptr;
while (cur != nullptr)
{
nxt = cur->next;
cur->next = pre;
pre = cur;
cur = nxt;
}
while (pre && head)
{
if (pre->val != head->val)
return false;
pre = pre->next;
head = head->next;
}
return true;
}
};
面试题 02.07. 链表相交
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* p1 = headA;
ListNode* p2 = headB;
while (p1 != p2)
{
p1 = p1 ? p1->next : headB;
p2 = p2 ? p2->next : headA;
}
return p1;
}
};
面试题 02.08. 环路检测
/**
* 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 == nullptr || head->next == nullptr) return nullptr;
ListNode* slow = head->next;
ListNode* fast = head->next->next;
while (slow != fast && slow && fast)
{
slow = slow->next;
fast = fast->next->next;
if (fast == nullptr || fast->next == nullptr)
return nullptr;
}
fast = head;
while (slow != fast && slow && fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
};
面试题 03.01. 三合一
class TripleInOne {
public:
int *stack;
int top[3];//存放三个栈的压入位置
int stackSize;
TripleInOne(int stackSize):stackSize(stackSize) {
stack = new int[stackSize * 3];
top[0] = top[1] = top[2] = 0;
}
void push(int stackNum, int value) {
if (top[stackNum] < stackSize)
stack[stackSize * stackNum + top[stackNum]++] = value;
}
int pop(int stackNum) {
if (top[stackNum] <= 0)
return -1;
else
return stack[stackSize * stackNum + (--top[stackNum])];
}
int peek(int stackNum) {
if (top[stackNum] <= 0)
return -1;
else
return stack[stackSize*stackNum + (top[stackNum] - 1)];
}
bool isEmpty(int stackNum) {
return top[stackNum] == 0;
}
};
/**
* Your TripleInOne object will be instantiated and called as such:
* TripleInOne* obj = new TripleInOne(stackSize);
* obj->push(stackNum,value);
* int param_2 = obj->pop(stackNum);
* int param_3 = obj->peek(stackNum);
* bool param_4 = obj->isEmpty(stackNum);
*/
面试题 03.02. 栈的最小值
class MinStack {
public:
/** initialize your data structure here. */
MinStack() {
}
void push(int x) {
if (sta1.empty())
{
sta1.push(x);
sta2.push(x);
}
else
{
sta1.push(x);
sta2.push(min(sta2.top(),x));
}
}
void pop() {
if (sta1.empty() || sta2.empty())
return;
sta2.pop();
sta1.pop();
}
int top() {
if (sta1.empty())
return -1;
return sta1.top();
}
int getMin() {
if (sta2.empty())
return -1;
return sta2.top();
}
private:
stack<int>sta1;
stack<int>sta2;
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(x);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
面试题 03.03. 堆盘子
class StackOfPlates {
list<stack<int>> stacks;
int cap;
public:
StackOfPlates(int cap) {
this->cap = cap;
}
void push(int val) {
if (cap == 0)
return;
if (stacks.empty() || stacks.back().size() == cap)
stacks.insert(stacks.end(), stack<int>());
stacks.back().push(val);
}
int pop() {
if (stacks.empty() || cap == 0)
return -1;
int ret = stacks.back().top();
stacks.back().pop();
if (stacks.back().empty())
stacks.pop_back();
return ret;
}
int popAt(int index) {
if (stacks.size() < index + 1 || cap == 0)
return -1;
auto it = stacks.begin();
for (int i = 0; i < index && it != stacks.end(); ++i, ++it);
int ret = it->top();
it->pop();
if (it->empty())
stacks.erase(it);
return ret;
}
};
/**
* Your StackOfPlates object will be instantiated and called as such:
* StackOfPlates* obj = new StackOfPlates(cap);
* obj->push(val);
* int param_2 = obj->pop();
* int param_3 = obj->popAt(index);
*/
面试题 03.04. 化栈为队
class MyQueue {
public:
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
while (!sta1.empty())
{
sta2.push(sta1.top());
sta1.pop();
}
sta1.push(x);
while (!sta2.empty())
{
sta1.push(sta2.top());
sta2.pop();
}
return;
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
if (sta1.empty())
return -1;
int tmp = sta1.top();
sta1.pop();
return tmp;
}
/** Get the front element. */
int peek() {
if (sta1.empty())
return -1;
else
return sta1.top();
}
/** Returns whether the queue is empty. */
bool empty() {
return sta1.empty();
}
private:
stack<int>sta1;
stack<int>sta2;
};
面试题 03.05. 栈排序
class SortedStack {
public:
SortedStack() {
}
void push(int val) {
while (!sta1.empty() && sta1.top() < val)
{
sta2.push(sta1.top());
sta1.pop();
}
sta1.push(val);
while (!sta2.empty())
{
sta1.push(sta2.top());
sta2.pop();
}
return;
}
void pop() {
if (!sta1.empty())
sta1.pop();
}
int peek() {
if (!sta1.empty())
return sta1.top();
else
return -1;
}
bool isEmpty() {
return sta1.empty();
}
private:
stack<int>sta1;
stack<int>sta2;
};
/**
* Your SortedStack object will be instantiated and called as such:
* SortedStack* obj = new SortedStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->isEmpty();
*/
面试题 03.06. 动物收容所
class AnimalShelf {
public:
AnimalShelf() {
}
void enqueue(vector<int> animal) {
if (animal.at(1) == 0)
{
m_queue_cat.push(animal);
}
else
{
m_queue_dog.push(animal);
}
}
vector<int> dequeueAny() {
vector<int> animal;
if (m_queue_cat.empty() && m_queue_dog.empty())
{
return vector<int>{-1, -1};
}
else if (!m_queue_cat.empty() && m_queue_dog.empty())
{
animal = m_queue_cat.front();
m_queue_cat.pop();
}
else if (m_queue_cat.empty() && !m_queue_dog.empty())
{
animal = m_queue_dog.front();
m_queue_dog.pop();
}
else
{
if (m_queue_cat.front().at(0) < m_queue_dog.front().at(0))
{
animal = m_queue_cat.front();
m_queue_cat.pop();
}
else
{
animal = m_queue_dog.front();
m_queue_dog.pop();
}
}
return animal;
}
vector<int> dequeueDog() {
if (m_queue_dog.empty())
{
return vector<int>{-1, -1};
}
vector<int> dog = m_queue_dog.front();
m_queue_dog.pop();
return dog;
}
vector<int> dequeueCat() {
if (m_queue_cat.empty())
{
return vector<int>{-1, -1};
}
vector<int> cat = m_queue_cat.front();
m_queue_cat.pop();
return cat;
}
private:
queue<vector<int>> m_queue_cat;
queue<vector<int>> m_queue_dog;
};
/**
* Your AnimalShelf object will be instantiated and called as such:
* AnimalShelf* obj = new AnimalShelf();
* obj->enqueue(animal);
* vector<int> param_2 = obj->dequeueAny();
* vector<int> param_3 = obj->dequeueDog();
* vector<int> param_4 = obj->dequeueCat();
*/
面试题 04.01. 节点间通路
深度优先搜索
class Solution {
public:
vector<vector<int>>adj;
bool sign = false;
bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) {
adj.resize(n);
for (auto item : graph)
{
adj[item[0]].push_back(item[1]);
}
dfs(start , target);
return sign;
}
void dfs(int start,int target)
{
if (start == target)
{
sign = true;
return;
}
for (int i = 0; i < adj[start].size(); i++)
{
dfs(adj[start][i],target);
}
return;
}
};
面试题 04.02. 最小高度树
二分递归
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
return recursive(nums, 0, nums.size() - 1);
}
TreeNode* recursive(vector<int>& nums, int l, int r)
{
if (l > r)
return nullptr;
int mid = (l + r)/2;
TreeNode* root = new TreeNode(nums[mid]);
root->left = recursive(nums, l , mid - 1);
root->right = recursive(nums, mid + 1 , r);
return root;
}
};
面试题 04.03. 特定深度节点链表
层序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
vector<ListNode*> listOfDepth(TreeNode* tree) {
queue<TreeNode*>que;
vector<ListNode*>ans;
que.push(tree);
while (!que.empty())
{
int size = que.size();
ListNode * head = new ListNode(0);
ListNode * tmp = head;
for (int i = 0;i < size;i++)
{
TreeNode* cur = que.front();
que.pop();
tmp->next = new ListNode(cur->val);
tmp = tmp->next;
if (cur->left)
que.push(cur->left);
if (cur->right)
que.push(cur->right);
}
ans.push_back(head->next);
}
return ans;
}
};
面试题 04.04. 检查平衡性
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool sign = true;
bool isBalanced(TreeNode* root) {
getDepth(root);
return sign;
}
int getDepth(TreeNode* root){
if (root == nullptr)
return 0;
int l = getDepth(root->left);
int r = getDepth(root->right);
if (abs(l - r) > 1) sign = false;
return max(l,r) + 1;
}
};
面试题 04.05. 合法二叉搜索树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int>arr;
bool isValidBST(TreeNode* root) {
inOrder(root);
for (int i = 1; i < arr.size(); i++)
{
if (arr[i] <= arr[i - 1])
return false;
}
return true;
}
void inOrder(TreeNode* root){
if (root == nullptr) return;
inOrder(root->left);
arr.push_back(root->val);
inOrder(root->right);
}
};
面试题 04.06. 后继者
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
stack<TreeNode*>sta;
TreeNode* tmp = root;
bool flag = false;
while (tmp || !sta.empty())
{
if (tmp)
{
sta.push(tmp);
tmp = tmp->left;
}
else
{
tmp = sta.top();
if (flag)
return tmp;
if (tmp == p)
flag = true;
sta.pop();
tmp = tmp->right;
}
}
return nullptr;
}
};
面试题 04.08. 首个共同祖先
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == nullptr || root == p || root == q)
{
return root;
}
TreeNode* l = lowestCommonAncestor(root->left, p, q);
TreeNode* r = lowestCommonAncestor(root->right, p, q);
if (l == nullptr) return r;
if (r == nullptr) return l;
return root;
}
};
面试题 04.09. 二叉搜索树序列
/*
首先,可以把二叉树看作一个拓扑图,一棵树的“根结点的数值”总是先于它的“左右子树中的结点的数值”被插入树中。
使用递归算法,依次枚举下一次插入的数值,变量buf用于构造数组。使用双端队列(变量q)存储这次可以插入的候选节点。
每次递归时,从双端队列q中取出候选值放入数组buf, 同时若候选值有左右子树,则将左右子树放进队列中。
若双端队列为空, 表示没有候选值,将buf放进结果ans中。
注意,每次选候选值结束时还原队列q与数组buf, 使其与输入时的值一致。
*/
class Solution {
private:
void Dfs(vector<vector<int>>& res, deque<TreeNode*>& q, vector<int>& buf) {
if(q.empty()) {
res.push_back(buf);
return;
}
for(int i = q.size(); i > 0; i--) {
TreeNode* root = q.front();
q.pop_front();
buf.push_back(root->val);
int count = 0;
if(root->left) {
q.push_back(root->left);
count++;
}
if(root->right) {
q.push_back(root->right);
count++;
}
Dfs(res, q, buf);
for(int j = 0; j < count; j++) {
q.pop_back();
}
q.push_back(root);
buf.pop_back();
}
}
public:
vector<vector<int>> BSTSequences(TreeNode* root) {
if(!root) {
return {{}};
}
deque<TreeNode*> q;
vector<vector<int>> res;
q.push_back(root);
vector<int> buf;
Dfs(res, q, buf);
return res;
}
};
面试题 04.10. 检查子树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool checkSubTree(TreeNode* t1, TreeNode* t2) {
if (recursive(t1, t2))
return true;
if (t1->left && checkSubTree(t1->left, t2))
return true;
if (t1->right && checkSubTree(t1->right, t2))
return true;
return false;
}
bool recursive(TreeNode* t1, TreeNode* t2) {
if (t1 == nullptr && t2 == nullptr)
return true;
else if (t1 == nullptr || t2 == nullptr)
return false;
if (t1->val != t2->val)
return false;
return recursive(t1->left, t2->left) && recursive(t1->right, t2->right);
}
};