文章目录
31.栈的压入、弹出序列
//java版
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
Stack<Integer> temp = new Stack<>();
int i = 0;
for(int num : pushed)
{
temp.push(num);//入栈
//模拟出栈
while(!temp.isEmpty() && temp.peek() == popped[i])
{
temp.pop();
i ++;
}
}
return temp.isEmpty();
}
}
//C++版
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
if(pushV.size() != popV.size()) return false;
stack<int> stk;
int i = 0;
//stk.top() == popV[i] stk.pop()
//stk.top() != popV[i] stk.push(x);
for(auto x : pushV)
{
stk.push(x);
while(stk.size() && stk.top() == popV[i])
{
stk.pop();
i ++;
}
}
return stk.empty();
}
};
32.从上到下打印二叉树
//java版
class Solution {
public int[] levelOrder(TreeNode root) {
if(root == null) return new int[0];
ArrayList<Integer> ans = new ArrayList<>();
//队列操作 保存根节点
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
while(!q.isEmpty())
{
//根结点
TreeNode r = q.poll();
ans.add(r.val);
//左子树
if(r.left != null) q.add(r.left);
//右子树
if(r.right != null) q.add(r.right);
}
int[] res = new int[ans.size()];
for(int i = 0; i < ans.size(); i ++)
res[i] = ans.get(i);
return res;
}
}
//C++版
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int> res;
if(!root) return res;
//非空
queue<TreeNode*> q;
q.push(root);
//bfs 广度优先遍历
while(q.size())
{
auto t = q.front();
q.pop();
res.push_back(t -> val);
if(t -> left) q.push(t -> left);
if(t -> right) q.push(t -> right);
}
return res;
}
};
33.二叉搜索树的后序遍历序列
//java版
class Solution {
public boolean verifyPostorder(int[] postorder) {
//左<根<右 二叉检索树
//后序遍历
//左右根
//递归
return dfs(postorder, 0, postorder.length - 1);
}
public boolean dfs(int[] arr, int l, int r)
{
if(l >= r) return true;//遍历到最后 都是true
//r对应 当前子树 根节点
//找到左右子树的临界点
int p = l;
while(arr[p] < arr[r]) p ++;
int m = p;
while(arr[p] > arr[r]) p ++;
return (p == r) && dfs(arr, l, m - 1) && dfs(arr, m, r - 1);
}
}
//C++版
class Solution {
public:
//后续遍历 左右根
//二叉搜索树特点 左孩子 < 父亲结点 < 右孩子
//左右根
//数组最后一个数字就是根节点/父亲结点
//左右子树分界点 与根节点相比较
vector<int> seq;
bool VerifySquenceOfBST(vector<int> sequence) {
seq = sequence;
if(seq.empty()) return false;
return dfs(0, seq.size() - 1);
}
bool dfs(int l, int r)
{
if(l >= r) return true;
//父亲结点
int father = seq[r];
//左子树 都小于
int k = l;
while(k < r && seq[k] < father) k ++;
//右子树 都大于
for(int i = k; i < r; i ++)
if(seq[i] < father)
return false;
return dfs(l, k - 1) && dfs(k, r - 1);
}
};
34.二叉树中和为某一值的路径
//java版
class Solution {
//前序遍历 根左右
LinkedList<List<Integer>> res = new LinkedList<>();//所有路径
LinkedList<Integer> path = new LinkedList<>();//单条路径
public List<List<Integer>> pathSum(TreeNode root, int sum) {
//递归函数
recur(root, sum);
return res;
}
void recur(TreeNode root, int target){
//找到 target = 0时候的叶节点
if(root == null) return;
path.add(root.val);
target -= root.val;
if(target == 0 && root.left == null && root.right == null)
res.add(new LinkedList(path));
recur(root.left, target);
recur(root.right, target);
//每次结束后 path必须清空
path.removeLast();
}
}
//C++版
class Solution {
public:
vector<vector<int> > res;
vector<int> path;
vector<vector<int> > FindPath(TreeNode* root,int sum) {
dfs(root, sum);
return res;
}
void dfs(TreeNode* root,int sum)
{
if(!root) return;
path.push_back(root -> val);
sum -= root -> val;
//sum == 0 且找到了叶节点 确定一条路径
if(!sum && !root -> left && !root -> right) res.push_back(path);
dfs(root -> left, sum);
dfs(root ->right, sum);
path.pop_back();
}
};
35.复杂链表的复制
//java版
class Solution {
public Node copyRandomList(Node head) {
if(head == null)
return null;
copy(head);//复制结点
copyrandom(head);//复制random指针
return divide(head);//分离出来
}
private void copy(Node head){
while(head != null)
{
Node clone = new Node(head.val);
Node nextNode = head.next;
head.next = clone;
clone.next = nextNode;
head = clone.next;
}
}
private void copyrandom(Node head){
while(head != null){
Node clone = head.next;
if(head.random != null)
{
Node randomnode = head.random;
clone.random = randomnode.next;
}
head = clone.next;
}
}
//7 8 9 10
//7 7’ 8 8‘ 9 9‘ 10 10’
private Node divide(Node head)
{
Node cloneNode = head.next;
Node cloneHead = cloneNode;
head.next = cloneNode.next;
head = head.next;
while(head != null)
{
cloneNode.next = head.next; // 8'
head.next = head.next.next;//8 9
head = head.next;
cloneNode = cloneNode.next;
}
return cloneHead;
}
}
//C++版
class Solution {
public:
RandomListNode* Clone(RandomListNode* head)
{
//1. 复制每个结点 next
//在两个结点之间新建一个结点 复制前驱
for(auto p = head; p;)
{
auto newp = new RandomListNode(p -> label);
//在p 和 p -> next之间插入newp
auto temp = p -> next;
p -> next = newp;
newp -> next = temp;
p = temp;
}
//random
//a -> next -> ramdom = a -> random -> next;
for(auto p = head; p; p = p -> next -> next)
{
if(p -> random)
p -> next -> random = p -> random -> next;
}
auto dummy = new RandomListNode(-1);
auto cur = dummy;
for(auto p = head; p; p = p -> next)
{
cur -> next = p -> next;//A'
cur = cur -> next;
p -> next = p -> next -> next;
}
return dummy -> next;
}
};
36.二叉搜索树与双向链表
//java版
class Solution {
Node pre,head;
public Node treeToDoublyList(Node root) {
if(root == null) return null;
dfs(root);//左根右 递增
//头尾结点处理一下
head.left = pre;
pre.right = head;
return head;
}
private void dfs(Node cur){
if(cur == null) return;
//左子树
dfs(cur.left);
//根结点
//left right指针
if(pre != null) pre.right = cur;
else head = cur;
cur.left = pre;
pre = cur;
//右子树
dfs(cur.right);
}
}
//C++版
class Solution {
public:
TreeNode* Convert(TreeNode* root)
{
if(!root) return NULL;
auto pairs = dfs(root);
return pairs.first;
}
pair<TreeNode*,TreeNode*> dfs(TreeNode* root)
{
if(!root -> left && ! root -> right) return {
root, root};
if(root -> left && root -> right)
{
auto lsides = dfs(root -> left), rsides = dfs(root -> right);
//左边返回
//{1,2} 2 ——> root root -> 2
lsides.second -> right = root;
root -> left = lsides.second;
//右边返回
//{1,2} 1——> root root -> 1
rsides.first -> left = root;
root -> right = rsides.first;
return {
lsides.first, rsides.second};
}
//只有左子树
if(root -> left)
{
auto lsides = dfs(root -> left);
//左边返回
//{1,2} 2 ——> root root -> 2
lsides.second -> right = root;
root -> left = lsides.second;
return {
lsides.first, root};
}
//只有右子树
if(root -> right)
{
auto rsides = dfs(root -> right);
//右边返回
//{1,2} 1——> root root -> 1
rsides.first -> left = root;
root -> right = rsides.first;
return {
root, rsides.second};
}
}
};
37.序列化二叉树
//java版
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root == null) return "[]";
//序列化为 "[1,2,3,null,null,4,5]"
StringBuilder res = new StringBuilder("[");
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
while(!q.isEmpty())
{
TreeNode t = q.poll();
if(t != null)
{
res.append(t.val + ",");
q.add(t.left);
q.add(t.right);
}
else
res.append("null,");
}
res.append("]");
return res.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if(data.equals("[]")) return null;
String[] vals = data.substring(1,data.length()-1).split(",");
TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
int i = 1;
while(!q.isEmpty())
{
TreeNode node = q.poll();
if(!vals[i].equals("null")){
node.left = new TreeNode(Integer.parseInt(vals[i]));
q.add(node.left);
}
i ++;
if(!vals[i].equals("null")){
node.right = new TreeNode(Integer.parseInt(vals[i]));
q.add(node.right);
}
i ++;
}
return root;
}
}
//C++版
class Solution {
public:
char* Serialize(TreeNode *root) {
string res;
dfs1(root, res);
char* p = new char[res.size() + 1];
strcpy(p, res.c_str());
return p;
}
void dfs1(TreeNode* root, string &res)
{
if(!root)
{
//#
res += "#,";
return;
}
res += to_string(root -> val) + ",";
dfs1(root -> left, res);
dfs1(root -> right, res);
}
//反序列化
TreeNode* Deserialize(char *str) {
int idx = 0;
return dfs2(str, idx);
}
TreeNode* dfs2(char* str, int &idx)
{
//确定长度 23 长度2 3 长度1
int len = idx;
while(str[len] != ',') len ++;
//空结点
if(str[idx] == '#')
{
idx = len + 1;
return NULL;
}
//非空结点
//计算数值
int num = 0;
//考虑符号+-
int sign = 1;
if(idx < len && str[idx] == '-') sign = -1, idx ++;
// ‘234’
for(int i = idx; i < len; i ++) num = num * 10 + str[i] - '0';
num *= sign;
//idx走到下一个数字
idx = len + 1;
//构建树
auto root = new TreeNode(num);
root -> left = dfs2(str, idx);
root -> right = dfs2(str, idx);
return root;
}
};
38.字符串的排列
//java版
class Solution {
Set<String> res = new HashSet<>();//保存结果
public String[] permutation(String s) {
if(s == null) return new String[]{
};
boolean[] visited = new boolean[s.length()];
dfs(s,"",visited);
return res.toArray(new String[res.size()]);
}
private void dfs(String s, String ch, boolean[] visited){
if(s.length() == ch.length())
{
res.add(ch);//abc
return;
}
for(int i = 0; i < s.length(); i ++)
{
char temp = s.charAt(i);
if(visited[i]) continue;
visited[i] = true;
dfs(s, ch + String.valueOf(temp), visited);
visited[i] = false;
}
}
}
//C++版
class Solution {
public:
vector<string> res;
string path;
vector<string> Permutation(string str) {
if(str == "") return res; //[""] []
//全排列
//可能重复字母 靠在一起 好判断
sort(str.begin(),str.end());
path.resize(str.size());
//全排列函数
dfs(str, 0, 0, 0);
//字典顺序
sort(res.begin(), res.end());
return res;
}
void dfs(string &str, int idx, int start, int state)
{
//已经找到一个排列
if(idx == str.size())
{
res.push_back(path);
return;
}
//单个排列没有排完
//相同字母而言 前后关系
//可能重复排序
//通过控制相对顺序不变确保不重复
if(idx == 0 || str[idx] != str[idx - 1]) start = 0;
//顺序往后
for(int i = start; i < str.size(); i ++)
if(!(state >> i & 1))
{
path[i] = str[idx];
dfs(str, idx + 1, i + 1, state + (1 << i));
}
}
};
39.数组中出现次数超过一半的数字
//java版
class Solution {
public int majorityElement(int[] nums) {
int val = -1, cnt = 0;
for(int num : nums)
{
//记录相同数字出现次数
//当前数字 == val cnt ++
//cnt == 0 val更新当前的
//最后肯定有cnt >=1 val
if(num == val)
cnt ++;
else{
//2 2 1 1 1
if(cnt >= 1) cnt --;
else{
val = num;
cnt = 1;
}
}
}
return val;
}
}
//C++版
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int val, cnt = 0;
for(auto x : numbers)
{
if(val == x)
cnt ++;
else{
if(cnt) cnt --;
else{
val = x;
cnt = 1;
}
}
}
cnt = 0;
for(auto x : numbers)
{
if(x == val)
cnt ++;
}
if(cnt * 2 > numbers.size())
return val;
return 0;
}
};
40.最小的k个数.txt
//java版
class Solution {
//快排
public int[] getLeastNumbers(int[] arr, int k) {
if(k == 0 || arr.length == 0)
return new int[0];
return qsk(arr,0, arr.length - 1, k - 1);
}
private int[] qsk(int[] nums, int l, int r, int k){
int j = quicksort(nums, l, r);
//j k对比得到要不要返回前k小的数组
if(j == k)
{
return Arrays.copyOf(nums,j + 1);
}
//否则 要根据 j k大小关系进行调整
return j > k ? qsk(nums,l, j - 1, k) : qsk(nums, j + 1, r, k);
}
private int quicksort(int[] nums, int l, int r){
int v = nums[l];
int i = l, j = r + 1;
while(true)
{
while(++i <= r && nums[i] < v);//i
while(--j >= l && nums[j] > v);//j
if(i >= j)
break;
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
nums[l] = nums[j];
nums[j] = v;
return j;//保证 nums[j] 左边是最小的j个数字
}
}
//C++版
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//暴力解答
/*
vector<int> res;
if(k > input.size()) return res;
sort(input.begin(),input.end());
for(int i = 0; i < k; i ++)
{
res.push_back(input[i]);
}
return res;
*/
//大根堆 k
vector<int> res;
if(k > input.size()) return res;
priority_queue<int> heap;
//找到最小的k个数字
for(auto x : input)
{
heap.push(x);
if(heap.size() > k) heap.pop();
}
//从大到小输入
while(heap.size()) res.push_back(heap.top()), heap.pop();
//从小到大
reverse(res.begin(), res.end());
return res;
}
};