算法笔试面试2
用两个栈来模拟实现队列
public class MyQueue {
private static Stack<Integer> inStack;
private static Stack<Integer> outStack;
public MyQueue(){
inStack = new Stack<>();
outStack = new Stack<>();
}
// 像队列中push元素
public void push(int x){
inStack.push(x);
}
// 从队列中弹出元素
public int pop(){
if (outStack.isEmpty()){
in2out();
}
return outStack.pop();
}
// 查看队首元素,但是不取出
public int peek(){
if(outStack.isEmpty()){
in2out();
}
return outStack.peek();
}
public boolean isEmpty(){
return inStack.isEmpty() && outStack.isEmpty();
}
public void in2out(){
while (!inStack.isEmpty()){
outStack.push(inStack.pop());
}
}
}
字符串解码
// TODO 待理解
public class Solution {
int ptr;
public String decodeString(String s) {
LinkedList<String> stk = new LinkedList<>();
ptr = 0;
while (ptr < s.length()) {
// 获取当前位置的字符
char cur = s.charAt(ptr);
// 判断当前字符是否是数字
if (Character.isDigit(cur)) {
// 处理数字,使数字完整
String digits = getDigits(s);
// 压入栈中
stk.addLast(digits);
} else if (Character.isLetter(cur) || cur == '[') {
// 处理普通字符和[
stk.addLast(String.valueOf(s.charAt(ptr++)));
} else {
// 遇见了] ,处理相匹配的[之间的字符
++ptr;
// 使用领一个list,将字符串进行组合
LinkedList<String> sub = new LinkedList<>();
// 如果不是[,就一直出栈,将出栈的元素放入到新建的sub栈中
while (!"[".equals(stk.peekLast())) {
sub.addLast(stk.removeLast());
}
// 因为栈的特点,导致组合的字符串和原本的字符串相比是倒序的,需要翻转一次
Collections.reverse(sub);
// 左括号[出栈
stk.removeLast();
// 此时栈顶为当前sub对应的字符串应该出现的次数
int repTime = Integer.parseInt(stk.removeLast());
StringBuffer t = new StringBuffer();
String o = getString(sub);
// 构造字符串
while (repTime-- > 0) {
t.append(o);
}
// 构造字符串
while (repTime-- > 0) {
t.append(o);
}
// 构造好的字符串入栈
stk.addLast(t.toString());
}
}
return getString(stk);
}
public String getDigits(String s) {
StringBuffer ret = new StringBuffer();
while (Character.isDigit(s.charAt(ptr))) {
ret.append(s.charAt(ptr++));
}
return ret.toString();
}
public String getString(LinkedList<String> v) {
StringBuffer ret = new StringBuffer();
for (String s : v) {
ret.append(s);
}
return ret.toString();
}
public static void main(String[] args) {
String s = "3[a]2[bc]";
Solution solution = new Solution();
String ret = solution.decodeString(s);
System.out.println(ret);
}
}
二叉树的中序遍历
方式一:采用递归的的方式
public class Solution {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
accessTree(root, res);
return res;
}
private void accessTree(TreeNode root, List<Integer> res) {
if (null == root) {
return;
}
// 说白了就是使用递归的方式进行遍历
accessTree(root.left, res);
res.add(root.val);
accessTree(root.right, res);
}
public static void main(String[] args) {
TreeNode left = new TreeNode(2,null,null);
TreeNode right = new TreeNode(3,null,null);
TreeNode root = new TreeNode(1,left,right);
Solution solution = new Solution();
List<Integer> treeList = solution.inorderTraversal(root);
System.out.println(treeList);
}
}
方式二:采用循环爹迭代的方式(借助栈)
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> stack = new LinkedList<>();
while (root != null || !stack.isEmpty()){
while (root != null){
stack.push(root);
root = root.left;
}
root = stack.pop();
res.add(root.val);
root = root.right;
}
return res;
}
二叉树的前序遍历
public class Solution {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
accessTree(root, res);
return res;
}
private void accessTree(TreeNode root, List<Integer> res) {
if (null == root) {
return;
}
// 说白了就是使用递归的方式进行遍历
res.add(root.val);
accessTree(root.left, res);
accessTree(root.right, res);
}
public static void main(String[] args) {
TreeNode left = new TreeNode(2,null,null);
TreeNode right = new TreeNode(3,null,null);
TreeNode root = new TreeNode(1,left,right);
Solution solution = new Solution();
List<Integer> treeList = solution.inorderTraversal(root);
System.out.println(treeList);
}
}
二叉树的后续遍历
public class Solution {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
accessTree(root, res);
return res;
}
private void accessTree(TreeNode root, List<Integer> res) {
if (null == root) {
return;
}
// 说白了就是使用递归的方式进行遍历
accessTree(root.left, res);
accessTree(root.right, res);
res.add(root.val);
}
public static void main(String[] args) {
TreeNode left = new TreeNode(2,null,null);
TreeNode right = new TreeNode(3,null,null);
TreeNode root = new TreeNode(1,left,right);
Solution solution = new Solution();
List<Integer> treeList = solution.inorderTraversal(root);
System.out.println(treeList);
}
}
对称二叉树
public class Solution {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public boolean isSymmetric(TreeNode root) {
if(root == null){
return true;
}
// 调用递归函数,比较左节点、右节点
return deepCheck(root.left,root.right);
}
private boolean deepCheck(TreeNode left, TreeNode right) {
// 递归的终止条件是两个节点都为空
// 或者两个节点中有一个为空
// 或者两个节点的值不相等
if(left == null && right == null){
return true;
}
if(left == null || right == null){
return false;
}
if (left.val != right.val){
return false;
}
// 再递归的比较 左节点的左孩子 和 右节点的右孩子
// 以及比较 左节点的右孩子 和右节点的左孩子
return deepCheck(left.left,right.right) && deepCheck(left.right,right.left);
}
public static void main(String[] args) {
TreeNode left = new TreeNode(2,null,null);
TreeNode right = new TreeNode(2,null,null);
TreeNode root = new TreeNode(1,left,right);
Solution solution = new Solution();
boolean flag= solution.isSymmetric(root);
System.out.println(flag);
}
}
二叉树的深度
public class Solution {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
}
public static void main(String[] args) {
TreeNode left = new TreeNode(2,null,null);
TreeNode right = new TreeNode(2,null,null);
TreeNode root = new TreeNode(1,left,right);
Solution solution = new Solution();
int depth = solution.maxDepth(root);
System.out.println(depth);
}
}
平衡二叉树
public class Solution {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public boolean isBalanced(TreeNode root) {
if(root == null){
return true;
}
return helper(root) != -1;
}
private int helper(TreeNode root) {
if(root == null){
return 0;
}
// 进行递归调用
int left = helper(root.left);
int right = helper(root.right);
if(left == -1 || right == -1 || Math.abs(left-right)>1){
return -1;
}
return Math.max(left,right)+1;
}
public static void main(String[] args) {
// 平衡二叉树
// TreeNode left = new TreeNode(2,null,null);
// TreeNode right = new TreeNode(2,null,null);
// TreeNode root = new TreeNode(1,left,right);
// 非平衡二叉树
TreeNode child01left = new TreeNode(2,null,null);
TreeNode child02left = new TreeNode(2,null,null);
TreeNode left = new TreeNode(2,child01left,null);
child01left.left = child02left;
TreeNode right = new TreeNode(2,null,null);
TreeNode root = new TreeNode(1,left,right);
Solution solution = new Solution();
boolean flag = solution.isBalanced(root);
System.out.println(flag);
}
}
翻转二叉树
public class Solution {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public TreeNode invertTree(TreeNode root) {
if(root == null){
return null;
}
invertTree(root.left);
invertTree(root.right);
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
return root;
}
// 二叉树的前序中序遍历
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
accessTree(root, res);
return res;
}
private void accessTree(TreeNode root, List<Integer> res) {
if (null == root) {
return;
}
// 说白了就是使用递归的方式进行遍历
accessTree(root.left, res);
res.add(root.val);
accessTree(root.right, res);
}
public static void main(String[] args) {
// 非平衡二叉树
TreeNode child01left = new TreeNode(1,null,null);
TreeNode child01right = new TreeNode(3,null,null);
TreeNode left = new TreeNode(2,child01left,child01right);
TreeNode child02left = new TreeNode(5,null,null);
TreeNode child02right = new TreeNode(7,null,null);
TreeNode right = new TreeNode(6,child02left,child02right);
TreeNode root = new TreeNode(4,left,right);
Solution solution = new Solution();
TreeNode node = solution.invertTree(root);
List<Integer> nodelist = solution.inorderTraversal(node);
System.out.println(nodelist);
}
}
LRU算法
定义:最近最少使用
底层基于 哈希表 + 双向链表 的数据结构来实现。
方式一:使用linkedhashmap来实现
public class LRUCacheByLinkedHashMap {
LinkedHashMap<Integer, Integer> map = null;
int capacity;
public LRUCacheByLinkedHashMap(int capacity){
map = new LinkedHashMap<>(capacity + 1, 0.75f,true);
this.capacity = capacity;
}
public int get(int key){
if (!map.containsKey(key)){
return -1;
}
return map.get(key);
}
public void put(int key,int value){
map.put(key,value);
if (map.size() > capacity){
Iterator<Integer> iterator = map.keySet().iterator();
map.remove(iterator.next());
}
}
}
方式二:使用HashMap实现
public class LRUCacheByHashMap {
class Node {
Node next;
Node pre;
int key;
int value;
Node(int k, int v) {
next = this;
pre = this;
key = k;
value = v;
}
}
HashMap<Integer,Node> map= new HashMap<>();
int capacity;
Node head;
public LRUCacheByHashMap(int capacity){
this.capacity= capacity;
head = new Node(-1,-1);
}
public int get(int key){
if(!map.containsKey(key)){
return -1;
}
Node node = map.get(key);
refresh(node); // 将取出来的这个节点刷新到头部
return node.value;
}
public void put(int key,int value){
if(map.containsKey(key)){
Node node = map.get(key);
node.value = value;
refresh(node);
}else {
Node node = new Node(key,value);
map.put(key,node);
refresh(node);
if(map.size() > capacity){
del();
}
}
}
private void refresh(Node node){
// 将这个node节点摘除
node.next.pre = node.pre;
node.pre.next = node.next;
node.next = head.next;
head.next.pre = node;
head.next = node;
node.pre = head;
}
// 删除队尾
private void del(){
Node node = head.pre;
node.next.pre = node.pre;
node.pre.next = node.next;
map.remove(node.key);
}
}
限制短信发送速率
// 假设我们有一个包含所有需要发送短信的电话号码的列表
List<String> phoneNumbers = Arrays.asList("1234567890", "0987654321", ...);
// 设置限速参数
int maxSmsPerSecond = 10; // 每秒最多发送的短信数量
int intervalBetweenSms = 1000 / maxSmsPerSecond; // 每条短信之间的间隔时间(毫秒)
// 记录上一次发送短信的时间
long lastSendTime = System.currentTimeMillis();
// 遍历电话号码列表,逐个发送短信
for (String phoneNumber : phoneNumbers) {
// 检查是否需要等待以满足限速要求
long currentTime = System.currentTimeMillis();
if (currentTime - lastSendTime < intervalBetweenSms) {
// 计算需要等待的时间
long waitTime = intervalBetweenSms - (currentTime - lastSendTime);
Thread.sleep(waitTime);
}
// 发送短信
sendSms("Your message here", phoneNumber);
// 更新上一次发送短信的时间
lastSendTime = System.currentTimeMillis();
}
输入一个字符串,统计字符串中每个字符出现的次数;输出字符及其对应的次数,按字符升序排列。
/**
* 编写一个 Java 程序,实现以下功能:
* 输入一个字符串,统计字符串中每个字符出现的次数;输出字符及其对应的次数,按字符升序排列。
* 示例输入:aaabbc
* 示例输出:a:3, b:2, c:1
*/
public class Solution {
public String countOfPerCharacter(String content) {
if (null == content || 0 == content.length()) {
return "字符串为空";
}
String[] arr = content.split("");
Map<String, Integer> map = new TreeMap<>();
for (int i = 0; i < arr.length; i++) {
if (map.containsKey(arr[i])) {
map.put(arr[i], map.get(arr[i]) + 1);
}else{
map.put(arr[i], 1);
}
}
// 使用TreeMap对字符串进行升序排序存储
StringBuilder result = new StringBuilder();
for (Map.Entry<String, Integer> entry : map.entrySet()) {
result.append(entry.getKey() + ":" + entry.getValue());
}
return result.toString();
}
public static void main(String[] args) {
String input = "aaabbc";
Solution solution = new Solution();
System.out.println(solution.countOfPerCharacter(input));
}
}