声明:内容较多, 没耐心的小伙伴先码后看
官方C语言题解:https://github.com/zhedahht/CodingInterviewChinese2
01.赋值运算符
这个就不用写了爬
02.手写单例
直接参考cyc的博客就好:https://github.com/CyC2018/CS-Notes/blob/master/notes/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%20%20-%20%E5%8D%95%E4%BE%8B.md
03.数组中重复的数字
/**
* @Description 03 数组中重复的数字 -小米有品
* @Author Zerah
* @Date 2019/11/11 16:41
**/
public class _03_DuplicationInArray {
public boolean dublicate(int [] nums , int length, int [] duplication){
// 入参数组校验
if (nums == null || nums.length<=0){
return false;
}
// 数组中元素校验
for (int i = 0; i < nums.length; i++) {
if (nums[i] <0 || nums[i] > length-1){
return false;
}
}
for (int i = 0; i < nums.length; i++) {
//当前下标i处存的元素不是i
while (nums[i] != i){
// 当前下标处的元素 和 下表为 num[i]处下标元素相等的话,说明存在重复元素
if (nums[i] == nums[nums[i]]){
duplication[0] = nums[i];
return true;
}
//交换元素
swap(nums, i, nums[i]);
}
}
return false;
}
private void swap(int nums[], int i, int j){
int t = nums[i];
nums [i] = nums[j];
nums [j] = t;
}
}
04.二维数组中的查找
/**
* @Description 二维数组中的查找
* @Author Zerah
* @Date 2019/11/11 16:56
**/
public class _04_FindInPartiallySortedMatrix {
public boolean findTarget(int target , int [][] matrix){
//入参数组校验
if (matrix == null || matrix.length == 0 || matrix[0].length ==0){
return false;
}
int rows = matrix.length;
int cols = matrix[0].length;
//从右上角开始,同理,可从左上角,左下角,右下角开始
int r =0,c = cols-1;
while (r <= rows -1 && c >=0){
if (target == matrix[r][c]){
return true;
}else if( target> matrix[r][c]){
r++;
}else if (target < matrix[r][c]){
c--;
}
}
return false;
}
}
05.替换空格
/**
* @Description 替换空格
* @Author Zerah
* @Date 2019/11/12 10:32
**/
public class _05_ReplaceSpaces {
public String replaceSpaces(String str){
if (str == null || str.length()<= 0){
return null;
}
StringBuilder sb = new StringBuilder(str);
//P1指向原始字符串的末尾索引,可以把字符串看作数组
int P1 = sb.length()-1;
for (int i=0; i<= P1; i++){
// 遍历的原始字符串中如果有空格
if (sb.charAt(i)==' '){
//因为 空格‘ ’ 替换为 ”%20“ 长度增加了2, 因此此处在字符串末尾拼接两个空格
sb.append(" ");
}
}
//P2指向扩容后的新字符串的末尾索引
int P2 = sb.length()-1;
//P1遍历到原始字符串开头,并且 P1和P2相遇后结束
while (P1>= 0 && P2>P1){
char c = sb.charAt(P1--);
//如果遇到空格,替换空格
if (c == ' '){
sb.setCharAt(P2--,'0');
sb.setCharAt(P2--,'2');
sb.setCharAt(P2--,'%');
}else {
//否则 将原始字符串中的字符迁移到扩容后的位置
sb.setCharAt(P2--,c);
}
}
return sb.toString();
}
}
06.从尾到头打印链表
/**
* @Description 06.从尾到头打印链表
* @Author Zerah
* @Date 2019/11/12 11:10
**/
public class _06_PrintListInReverseOrder {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode){
Stack<Integer> stack = new Stack<>();
// 校验,入栈
while (listNode !=null){
stack.add(listNode.val);
listNode = listNode.next;
}
ArrayList<Integer> ret = new ArrayList<>();
// 出栈,并且存入ArrayList
while (!stack.isEmpty()){
ret.add(stack.pop());
}
return ret;
}
public class ListNode{
private Integer val;
private ListNode next;
}
}
07.重建二叉树
前序遍历的第一个值为根节点的值,使用这个值将中序遍历结果分成两个部分,左部分为树的左子树中序遍历结果,右部分为树的右子树中序遍历结果
/**
* @Description 07.重建二叉树
* @Author Zerah
* @Date 2019/11/12 15:51
**/
public class _07_ConstructBinaryTree {
// 缓存中序遍历数组
private Map<Integer,Integer> indexForInOrders = new HashMap<>();
/**
*
* @param pre 前序数组
* @param in 中序数组
* @return
*/
public TreeNode reConstructBinaryTree(int [] pre, int[] in){
for (int i=0; i<in.length; i++){
//中序遍历的数顺序put进map中
indexForInOrders.put(in[i],i);
}
return reConstructBinaryTree(pre,0,pre.length-1, 0);
}
private TreeNode reConstructBinaryTree(int []pre, int preL, int preR, int inL){
if (preL > preR){
return null;
}
TreeNode root = new TreeNode(pre[preL]);
int inIndex = indexForInOrders.get(root.val);
int leftTreeSize = inIndex - inL;
root.left = reConstructBinaryTree(pre,preL+1, preL + leftTreeSize, inL);
root.right = reConstructBinaryTree(pre, preL + leftTreeSize+1, preR, inL+leftTreeSize +1);
return root;
}
static class TreeNode{
int val;
TreeNode left;
TreeNode right;
public TreeNode(int node){
this.val = node;
}
}
public static void main(String[] args) {
int pre[] = {3,9,20,15,7};
int in[] = {9,3,15,20,7};
_07_ConstructBinaryTree tree = new _07_ConstructBinaryTree();
TreeNode treeNode = tree.reConstructBinaryTree(pre, in);
System.out.println(treeNode);
}
}
09.用两个栈实现队列
思路参考:https://blog.csdn.net/csdnnews/article/details/86570636
package com.zerah.concurrent.ToOffer;
import java.util.Stack;
/**
* @Description 使用两个栈实现队列
* @Author Zerah
* @Date 2019/12/16 17:31
**/
public class _09_QueueWith2Stack {
Stack<Integer> in = new Stack<>();
Stack<Integer> out = new Stack<>();
/**
* 入队 O(1)
* @param node
*/
public void push(int node){
in.push(node);
}
/**
* 出队 O(n)
* @return
*/
public int pop(){
if (out.isEmpty()){
while (!in.isEmpty()){
out.push(in.pop());
}
}
if (out.isEmpty()){
return -1;
}
return out.pop();
}
/**
* 判空
* @return
*/
public boolean isEmpty(){
return in.isEmpty() && out.isEmpty();
}
}
10.斐波那契数列
这个题也是在美团三面挂了的题,只恨当时蠢,至写出了递归,面试官又问了循环实现,以及当这个数很大时怎么处理的思路,因为这个题,三面给挂了,哭了,所以小伙伴们不仅仅要会解体,简单的题要有优化的思路offer才更有保障,引以为戒
package com.zerah.concurrent.ToOffer;
/**
* @Description 斐波那契数列
* @Author Zerah
* @Date 2019/12/17 12:32
**/
public class _10_Fibonacci {
/**
* 递归实现
* @param n
* @return
*/
public static int fibonacci_self(int n){
if (n <= 0){
return 0;
}
if (n ==1 ){
return 1;
}
return fibonacci_self(n-1)+ fibonacci_self(n-2);
}
/**
* dp 实现,将自问题的解缓存起来,避免重复求解子问题
* @param n
*/
public static int fibonacci_dp(int n){
if(n<=1){
return n;
}
int [] fib = new int[n+1];
fib[1] =1;
for (int i=2;i<=n ; i++){
fib[i] = fib[i-1]+ fib[i-2];
}
return fib[n];
}
/**
* 循环实现 ;因为 fib(i) 只和fib(i-1)以及fib(i-2)有关,因此可以通过前两个值从下而上解决问题
* @param n
*/
public static int fibonacci_for(int n){
if (n<=1) return n;
int pre =0,curr=1;
int fib = 0;
for (int i=2; i<= n; i++){
fib = pre+ curr;
pre =curr;
curr =fib;
}
return fib;
}
public static void main(String[] args) {
System.out.println(fibonacci_self(6));
System.out.println(fibonacci_dp(6));
System.out.println(fibonacci_for(6));
}
}