36.两个链表的第一个公共节点

题目描述

输入两个链表,找出它们的第一个公共结点。
1.具有重合节点的两个链表是一个Y字性,用两个堆栈放这两个链表,从尾部开始遍历,直到遍历到最后一个重合节点。
这种算法时间复杂度为O(m+n),但是空间复杂度也是O(m+n),相当于是空间换时间
/*
public class ListNode {
int val;
ListNode next = null; ListNode(int val) {
this.val = val;
}
}*/
import java.util.*;
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
Stack<ListNode> s1=new Stack<ListNode>();
Stack<ListNode> s2=new Stack<ListNode>(); while(pHead1!=null){
s1.add(pHead1);
pHead1=pHead1.next;
} while(pHead2!=null){
s2.add(pHead2);
pHead2=pHead2.next;
} ListNode foundNode =null;
ListNode node =null;
while(!s1.isEmpty() && !s2.isEmpty()){
node=s1.pop();
if(node==s2.pop())
foundNode =node;
else
return foundNode;
}
return foundNode;
}
}

2.利用HashSet中元素不能重复的原理,首先遍历一个链表进行存放,然后遍历另外一个链表,找到第一个与Set中元素相同的节点。

public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode current1 = pHead1;
ListNode current2 = pHead2; HashSet <ListNode> hashSet = new HashSet<ListNode>();
while (current1 != null) {
hashSet.add(current1);
current1 = current1.next;
}
while (current2 != null) {
if (hashSet.contains(current2))
return current2;
current2 = current2.next;
} return null; }

3.首先遍历两个链表得到它们的长度,就能知道哪个链表比较长,以及长的链表比短的链表多几个节点。第二次遍历的时候,在较长的链表上线走若干步,接着同时在两个链表上遍历,找到的第一个相同的节点就是它们的第一个公共节点。

链接:https://www.nowcoder.com/questionTerminal/6ab1d9a29e88450685099d45c9e31e46
来源:牛客网 public ListNode FindFirstCommonNodeII(ListNode pHead1, ListNode pHead2) {
        ListNode current1 = pHead1;// 链表1
        ListNode current2 = pHead2;// 链表2
        if (pHead1 == null || pHead2 == null)
            return null;
        int length1 = getLength(current1);
        int length2 = getLength(current2);
        // 两连表的长度差
         
        // 如果链表1的长度大于链表2的长度
        if (length1 >= length2) {
            int len = length1 - length2;
            // 先遍历链表1,遍历的长度就是两链表的长度差
            while (len > ) {
                current1 = current1.next;
                len--;
            }
 
        }
        // 如果链表2的长度大于链表1的长度
        else if (length1 < length2) {
            int len = length2 - length1;
            // 先遍历链表1,遍历的长度就是两链表的长度差
            while (len > ) {
                current2 = current2.next;
                len--;
            }
 
        }
        //开始齐头并进,直到找到第一个公共结点
        while(current1!=current2){
            current1=current1.next;
            current2=current2.next;
        }
        return current1;
 
    }
 
    // 求指定链表的长度
    public static int getLength(ListNode pHead) {
        int length = ;
 
        ListNode current = pHead;
        while (current != null) {
            length++;
            current = current.next;
        }
        return length;
    }

37.数字在排序数组中出现的次数

题目描述

统计一个数字在排序数组中出现的次数。
注意是在排序后的数组中,遍历数组找到目标数字,当遍历到和目标数字不相等的位置后就可以不再遍历,减小时间复杂度。
public class Solution {
public int GetNumberOfK(int [] array , int k) {
int number = ;
int flag = ;
for(int i: array){
if(i == k){
number++;
flag = ;
}else if(i != k && flag == ){
return number;
}
}
return number;
}
}

二分法:

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        int length = array.length;
        if(length == ){
            return ;
        }
        int firstK = getFirstK(array, k, , length-);
        int lastK = getLastK(array, k, , length-);
        if(firstK != - && lastK != -){
             return lastK - firstK + ;
        }
        return ;
    }
    //递归写法
    private int getFirstK(int [] array , int k, int start, int end){
        if(start > end){
            return -;
        }
        int mid = (start + end) >> ;
        if(array[mid] > k){
            return getFirstK(array, k, start, mid-);
        }else if (array[mid] < k){
            return getFirstK(array, k, mid+, end);
        }else if(mid- >= && array[mid-] == k){
            return getFirstK(array, k, start, mid-);
        }else{
            return mid;
        }
    }
    //循环写法
    private int getLastK(int [] array , int k, int start, int end){
        int length = array.length;
        int mid = (start + end) >> ;
        while(start <= end){
            if(array[mid] > k){
                end = mid-;
            }else if(array[mid] < k){
                start = mid+;
            }else if(mid+ < length && array[mid+] == k){
                start = mid+;
            }else{
                return mid;
            }
            mid = (start + end) >> ;
        }
        return -;
    }
}
public class Solution {
public int GetNumberOfK(int [] array , int k) {
int first = firstGreatOrEqual(array, k);
int last = firstGreat(array, k);
return last - first;
} public int firstGreatOrEqual(int[] array,int key) {
int left = ;
int right = array.length - ; while (left <= right) {
int mid = (left + right) / ;
if (array[mid] >= key) {
right = mid - ;
}
else {
left = mid + ;
}
}
return left;
} public int firstGreat(int[] array, int key) {
int left = ;
int right = array.length - ; while (left <= right) {
int mid = (left + right) / ;
if (array[mid] > key) {
right = mid - ;
}
else {
left = mid + ;
}
}
return left;
} }

38.二叉树的深度

题目描述

输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
1.采用递归方法
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null; public TreeNode(int val) {
this.val = val; } }
*/
public class Solution {
public int TreeDepth(TreeNode root) {
if(root == null)
return ;
int left = TreeDepth(root.left);
int right = TreeDepth(root.right); return (left>right)?(left+):(right+);
}
}

2.采用层次遍历的方式

先知道下一层树的个数,然后count++,相等时候,结束一层的层序遍历。

链接:https://www.nowcoder.com/questionTerminal/435fb86331474282a3499955f0a41e8b
来源:牛客网 import java.util.Queue;
import java.util.LinkedList;
 
public class Solution {
    public int TreeDepth(TreeNode pRoot)
    {
        if(pRoot == null){
            return ;
        }
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(pRoot);
        int depth = , count = , nextCount = ;
        while(queue.size()!=){
            TreeNode top = queue.poll();
            count++;
            if(top.left != null){
                queue.add(top.left);
            }
            if(top.right != null){
                queue.add(top.right);
            }
            if(count == nextCount){
                nextCount = queue.size();
                count = ;
                depth++;
            }
        }
        return depth;
    }
}

39.平衡二叉树

题目描述

输入一棵二叉树,判断该二叉树是否是平衡二叉树。
平衡二叉树左右树的高度不超过1。
递归获取树的高度
public class Solution {
private boolean isBalanced = true;
public boolean IsBalanced_Solution(TreeNode root) {
height(root);
return isBalanced;
} private int height(TreeNode root){
if(root == null)
return ;
int left = height(root.left);
int right = height(root.right);
if(Math.abs(left-right)>)
isBalanced = false;
return +Math.max(left,right);
}
}

40.数组中只出现一次的数字

题目描述

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

思路:
//使用堆栈来做辅助功能,将数组先排序,依次入栈,每一次数组入栈时和当前堆栈的栈头比较,如果当前堆栈为空,就入栈,如果和当前栈头的元素相同就出栈,当数组中左右元素都入栈完毕,那么当前栈中剩余的2个元素就是只出现一次的两个元素

时间复杂度为O(n2),空间复杂度为O(n)

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.*;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
Arrays.sort(array);
Stack<Integer> stack = new Stack<Integer>();
int len = array.length; if(array == null){
num1[] = ;
num2[] = ;
}
for(int x = ;x<len;x++){
if(stack.isEmpty()){
stack.push(array[x]);
}else{
if(stack.peek() == array[x])
stack.pop();
else
stack.push(array[x]);
}
}
num1[] = stack.pop();
num2[] = stack.pop();
}
}

用ArrayList,思路和前面的一致

时间复杂度为O(n2),空间复杂度为O(n)

remove不装箱的话会被当作按照下标删除,add会自动装箱

链接:https://www.nowcoder.com/questionTerminal/e02fdb54d7524710a7d664d082bb7811
来源:牛客网 import java.util.ArrayList;
public class Solution {
        public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
                ArrayList<Integer>list=new ArrayList<Integer>();
                for(int i=;i<array.length;i++)
                    {
                        if(!list.contains(array[i]))
                            list.add(array[i]);
                        else
                            list.remove(new Integer(array[i]));
                    }
                if(list.size()>)
                    {
                        num1[]=list.get();
                        num2[]=list.get();
                    }
        }
}

最好的方法:

时间复杂度为O(n),空间复杂度为O(1)

此题考察的是异或运算的特点:即两个相同的数异或结果为0。
此题用了两次异或运算特点:
(1)第一次使用异或运算,得到了两个只出现一次的数相异或的结果。
(2)因为两个只出现一次的数肯定不同,即他们的异或结果一定不为0,一定有一个位上有1。另外一个此位上没有1,我们可以根据此位上是否有1,将整个数组重新划分成两部分,一部分此位上一定有1,另一部分此位上一定没有1,然后分别对每部分求异或,因为划分后的两部分有这样的特点:其他数都出现两次,只有一个数只出现一次。因此,我们又可以运用异或运算,分别得到两部分只出现一次的数。
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.*;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) { int diff = ;
for(int num : array)
diff ^= num;
for(int num : array){
if((num & diff) == )
num1[] ^= num;
else
num2[] ^= num;
}
}
}

41.和为S的连续证书序列

输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序

链接:https://www.nowcoder.com/questionTerminal/c451a3fd84b64cb19485dad758a55ebe
来源:牛客网 import java.util.ArrayList;
/*
*初始化small=1,big=2;
*small到big序列和小于sum,big++;大于sum,small++;
*当small增加到(1+sum)/2是停止
*/
public class Solution {
    public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
        ArrayList<ArrayList<Integer>> lists=new ArrayList<ArrayList<Integer>>();
        if(sum<=){return lists;}
        int small=;
        int big=;
        while(small!=(+sum)/){          //当small==(1+sum)/2的时候停止
            int curSum=sumOfList(small,big);
            if(curSum==sum){
                ArrayList<Integer> list=new ArrayList<Integer>();
                for(int i=small;i<=big;i++){
                    list.add(i);
                }
                lists.add(list);
                small++;big++;
            }else if(curSum<sum){
                big++;
            }else{
                small++;
            }
        }
        return lists;
    }
     
    public int sumOfList(int head,int leap){        //计算当前序列的和
        int sum=head;
        for(int i=head+;i<=leap;i++){
            sum+=i;
        }
        return sum;
    }
}

42.和为S 的两个数字

题目描述

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
思路:左右夹逼方法,遇到的第一组满足和为S的数字即是乘积最小的。
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> al = new ArrayList<Integer>();
if(array == null)
return al;
int ahead = ;
int behind = array.length-;
while(ahead < behind){
int curSum = array[ahead] + array[behind];
if(sum == curSum){
al.add(array[ahead]);
al.add(array[behind]);
break;
}else if(curSum > sum){
behind--;
}else{
ahead++;
}
}
return al;
}
}

43.左旋转字符串

题目描述

汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”
public class Solution {
public String LeftRotateString(String str,int n) {
if(str.length() == )
return ""; char[] a = str.toCharArray();
char[] result = new char[a.length];
for(int i=;i<a.length-n;i++){
result[i] = a[n+i];
}
for(int i=;i<n;i++){
result[a.length-n+i] = a[i];
} return String.valueOf(result); }
}
public class Solution {
public String LeftRotateString(String str,int n) {
if(str.length()==)
return "";
int len = str.length();
str += str;
return str.substring(n, len+n);
}
}
public class Solution {
public String LeftRotateString(String str,int n) {
if(str.length()==)
return "";
        //把原字符串截取成俩字符串,然后拼接
        String s1 = str.substring(, n);
        String s2 = str.substring(n,str.length());
        return s2 + s1;
}
}

44.翻转单词顺序列

题目描述

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
注意://要trim(),可能输入多个空格组成的字符串
public class Solution {
public String ReverseSentence(String str) {
if(str==null||str.length()==||str.trim().length()==)
return str; String[] a = str.split(" ");
StringBuffer sb = new StringBuffer();
for(int i = ;i<a.length;i++){
if(i!=a.length-)
sb.append(String.valueOf(a[a.length--i])).append(" ");
else
sb.append(String.valueOf(a[a.length--i]));
}
return sb.toString();
}
}

45.扑克牌算子

思路1:

1.将数组排序

2.找到第一个不出现0的位置,记作min

3.max - min < 5 则是顺子

import java.util.Arrays;
public class Solution {
public boolean isContinuous(int [] numbers) {
if(numbers == null || numbers.length == )
return false; Arrays.sort(numbers);
int length = numbers.length;
int positionFlag = ;
boolean endZeroFlag = true;
for(int i= ; i<length-;i++){
if(numbers[i] == ){
positionFlag = i+;
endZeroFlag = false;
}else {
endZeroFlag = true;
}
if(endZeroFlag == true && numbers[i] == numbers[i+])
return false;
} if(numbers[length-] - numbers[positionFlag] >= )
return false;
else
return true;
}
}

思路2:

1、排序 
2、计算所有相邻数字间隔总数 
3、计算0的个数 
4、如果2、3相等,就是顺子 
5、如果出现对子,则不是顺子
链接:https://www.nowcoder.com/questionTerminal/762836f4d43d43ca9deb273b3de8e1f4
来源:牛客网 import java.util.Arrays;
public class Solution {
    public boolean isContinuous(int[] numbers) {
        int numOfZero = ;
        int numOfInterval = ;
        int length = numbers.length;
        if(length == ){
           return false;
        }
        Arrays.sort(numbers);
        for (int i = ; i < length - ; i++) {
            // 计算癞子数量
            if (numbers[i] == ) {
                numOfZero++;
                continue;
            }
            // 对子,直接返回
            if (numbers[i] == numbers[i + ]) {
                return false;
            }
            numOfInterval += numbers[i + ] - numbers[i] - ;
        }
        if (numOfZero >= numOfInterval) {
            return true;
        }
        return false;
    }
}

46.圆圈中最后剩下的数字

0,1,2,。。。n这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字,求出这个圆圈里剩下的最后一个数字。

1.数组来模拟环

public static int findLastNumber(int n,int m){
        if(n<||m<) return -;
        int[] array = new int[n];
        int i = -,step = , count = n;
        while(count>){   //跳出循环时将最后一个元素也设置为了-1
            i++;          //指向上一个被删除对象的下一个元素。
            if(i>=n) i=;  //模拟环。
            if(array[i] == -) continue; //跳过被删除的对象。
            step++;                     //记录已走过的。
            if(step==m) {               //找到待删除的对象。
                array[i]=-;
                step = ;
                count--;
            }        
        }
        return i;//返回跳出循环时的i,即最后一个被设置为-1的元素
    }

2.用ArrayList做

index = (index + m) % data.size();

import java.util.ArrayList;
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if (m == || n == ) {
return -;
}
ArrayList<Integer> data = new ArrayList<Integer>();
for (int i = ; i < n; i++) {
data.add(i);
}
int index = -;
while (data.size() > ) {
index = (index + m) % data.size();
data.remove(index);
index--;
}
return data.get();
}
}

47.求1+2+3+...+n

求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

思路1:

通常求求1+2+3+...+n除了用(乘法)公式n(n+1)/2,无外乎循环和递归两种思路,由于已经明确限制for和while的使用,循环已经不能再用了。递归函数也需要用if或者条件判断语句判断是继续递归下去还是终止递归,但是现在题目已经不允许使用这两种语句。

1.需利用逻辑与的短路特性实现递归终止。
2.当n==0时,(n>0)&&((sum+=Sum_Solution(n-1))>0)只执行前面的判断,为false,然后直接返回0
3.当n>0时,执行sum+=Sum_Solution(n-1),实现递归计算Sum_Solution(n)。
public class Solution {
public int Sum_Solution(int n) {
int sum = n;
boolean ans = (n>) && ((sum += Sum_Solution(n-))>);
return sum;
}
}

思路2:

用异常退出递归

public class Solution {
    public int Sum_Solution(int n) {
        return sum(n);
    }
    int sum(int n){
        try{
            int i = %n;
            return n+sum(n-);
        }
        catch(Exception e){
            return ;
        }
    }
}

思路3:

Math的幂函数,但是底层还是用了乘法

public class Solution {
    public int Sum_Solution(int n) {
        n = (int) (Math.pow(n, )+n)>>;
return n;
    }
}

48.不做加减乘除做加法

首先看十进制是如何做的: 5+7=12,三步走

第一步:相加各位的值,不算进位,得到2。

第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。

第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。

同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111

第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。

第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。

第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。 继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。

public class Solution {
 public int Add(int num1,int num2) {
        while (num2!=) {
            int temp = num1^num2;
            num2 = (num1&num2)<<;
            num1 = temp;
        }
        return num1;
    }
}

49.将字符串转换成整数

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

思路:

1.首先判断字符串第一个字符是不是‘-’‘+’号,如果是,则从第二个字符开始判断是不是数字;如果是‘-’,记录负数的标记

2.遍历每一个数字的asc码,if (a[i] < 48 || a[i] > 57return 0

public class Solution {
public int StrToInt(String str) {
if (str.equals("") || str.length() == )
return ;
char[] a = str.toCharArray();
int sum = ;
int fuhao = ;
boolean fushu = false;
if(a[] == '-'){
fuhao = ;
fushu = true;
}else if (a[] == '+'){
fuhao = ;
} for (int i = fuhao; i < a.length; i++)
{
if (a[i] < || a[i] > )
return ;
sum = sum * + a[i] - ;
}
return fushu == false ? sum : sum * (-);
}
}

犯规写法:

public int StrToInt(String str) {
        int result;
        if (str == "" || str == null ) {
            return ;
        }
        try {
           result = Integer.valueOf(str);
        } catch (NumberFormatException e) {
            return ;
        }
        return result;
    }

50.数组中重复的数字

题目描述

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
思路:
构造一个长度为n的boolean数组,思想类似hash算法取地址存放,根据输入数组中每个数字大小决定将boolean数组哪个位置的值置位为true。
public class Solution {

     public boolean duplicate(int numbers[],int length,int [] duplication) {
boolean [] a = new boolean[length];
for(int i=;i<length; i++){
if(a[numbers[i]] == true){
duplication[] = numbers[i];
return true;
}
a[numbers[i]] = true;
}
return false;
}
}

使用Array.sort()或者HashSet(hashSet.add方法返回的是boolean值),但是补不能保证题目条件不能保证题目条件:如果输入长度为7的数组{ 7 5 6 7 5 3 1},那么对应的输出是第一个重复的数字2。

链接:https://www.nowcoder.com/questionTerminal/623a5ac0ea5b4e5f95552655361ae0a8
来源:牛客网 import java.util.*;
public class Solution {   
public boolean duplicate(int numbers[],int length,int [] duplication) {
//方法1:
     if(numbers == null || numbers.length == ) return false;
        Arrays.sort(numbers);
        int flag = ;//做标记
        for(int i=;i<length-;i++) {
            if(numbers[i] == numbers[i+]) {
                duplication[] = numbers[i];
                flag = ;
                break;
            }
        }
        return flag == ? true:false;
//方法2:
        HashSet<Integer> hs = new HashSet<>();
        for(int i=;i<length;i++) {
            if(!hs.add(numbers[i])) {
                duplication[]=numbers[i];
                return true;
            }
        }
        return false;
    }
}
 51.构建乘积数组
 
剑指的思路:
B[i]的值可以看作下图的矩阵中每行的乘积。
下三角用连乘可以很容求得,上三角,从下向上也是连乘。
因此我们的思路就很清晰了,先算下三角中的连乘,即我们先算出B[i]中的一部分,然后倒过来按上三角中的分布规律,把另一部分也乘进去。
import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
int length = A.length;
int [] B = new int[length];
B[] = ;
//计算下三角连乘
for(int i = ;i<length;i++){
B[i] = B[i-]*A[i-];
}
int temp = ;
//计算上三角
for(int j=length -;j>=;j--){
temp *= A[j+];
B[j] *= temp;
}
return B;
}
}

52.正则表达式的匹配

思路:

当模式中的第二个字符不是“*”时:
、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的。
、如果 字符串第一个字符和模式中的第一个字符相不匹配,直接返回false。 而当模式中的第二个字符是“*”时:
如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。如果字符串第一个字符跟模式第一个字符匹配,可以有3种匹配方式:
、模式后移2字符,相当于x*被忽略;
、字符串后移1字符,模式后移2字符;
、字符串后移1字符,模式不变,即继续匹配字符下一位,因为*可以匹配多位; 这里需要注意的是:Java里,要时刻检验数组是否越界。
public class Solution {
public boolean match(char[] str, char[] pattern) {
if (str == null || pattern == null) {
return false;
}
int strIndex = ;
int patternIndex = ;
return matchCore(str, strIndex, pattern, patternIndex);
} public boolean matchCore(char[] str, int strIndex, char[] pattern, int patternIndex) {
//有效性检验:str到尾,pattern到尾,匹配成功
if (strIndex == str.length && patternIndex == pattern.length) {
return true;
}
//pattern先到尾,匹配失败
if (strIndex != str.length && patternIndex == pattern.length) {
return false;
}
//模式第2个是*,且字符串第1个跟模式第1个匹配,分3种匹配模式;如不匹配,模式后移2位
if (patternIndex + < pattern.length && pattern[patternIndex + ] == '*') {
if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) {
return matchCore(str, strIndex, pattern, patternIndex + )//模式后移2,视为x*匹配0个字符
|| matchCore(str, strIndex + , pattern, patternIndex + )//视为模式匹配1个字符
|| matchCore(str, strIndex + , pattern, patternIndex);//*匹配1个,再匹配str中的下一个
} else {
return matchCore(str, strIndex, pattern, patternIndex + );
}
}
//模式第2个不是*,且字符串第1个跟模式第1个匹配,则都后移1位,否则直接返回false
if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) {
return matchCore(str, strIndex + , pattern, patternIndex + );
}
return false;
}
}

53.表示数值的字符串

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。

犯规写法1:使用正则表达式

public class Solution {

 public boolean isNumeric(char[] str) {
        String string = String.valueOf(str);
        return string.matches("[\\+-]?[0-9]*(\\.[0-9]*)?([eE][\\+-]?[0-9]+)?");
    }
}

犯规写法2:使用自带API

public class Solution {
    public boolean isNumeric(char[] str) {
        try {
            double re = Double.parseDouble(new String(str));
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }
}

正规解法:

参考剑指offer

分成A[.[B]][e|EC]或者.B[e|EC]

分表验证ABC三部分,AC都是可带正负符号的整数,B为无符号整数

//参见剑指offer
public class Solution {
    private int index = ;
  
    public boolean isNumeric(char[] str) {
        if (str.length < )
            return false;
         
        boolean flag = scanInteger(str);
         
        if (index < str.length && str[index] == '.') {
            index++;
            flag = scanUnsignedInteger(str) || flag;
        }
         
        if (index < str.length && (str[index] == 'E' || str[index] == 'e')) {
            index++;
            flag = flag && scanInteger(str);
        }
         
        return flag && index == str.length;
         
    }
     
    private boolean scanInteger(char[] str) {
        if (index < str.length && (str[index] == '+' || str[index] == '-') )
            index++;
        return scanUnsignedInteger(str);
         
    }
     
    private boolean scanUnsignedInteger(char[] str) {
        int start = index;
        while (index < str.length && str[index] >= '' && str[index] <= '')
            index++;
        return start < index; //是否存在整数
    }
}

54.字符流中第一个不重复的字符

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。

思路1:

使用LinkedHashMap实现,注意不能使用hashmap,因为题目要求得到的是第一个不重复的字符,所以必须有序。

import java.util.LinkedHashMap;
public class Solution {
LinkedHashMap<Character,Integer> map =new LinkedHashMap<Character,Integer>();
public void Insert(char ch)
{
if(map.containsKey(ch)){
map.put(ch, map.get(ch)+);
}else{
map.put(ch, );
}
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
for(char key:map.keySet()){
if(map.get(key) == )
return key; }
return '#';
}
}

思路2:

一个256大小的数组来实现一个简易的哈希表

public class Solution
{    
    int[] hashtable=new int[];
    StringBuffer s=new StringBuffer();
    //Insert one char from stringstream
    public void Insert(char ch)
    {
        s.append(ch);
        if(hashtable[ch]==)
            hashtable[ch]=;
        else hashtable[ch]+=;
    }
  //return the first appearence once char in current stringstream
    public char FirstAppearingOnce()
    {
      char[] str=s.toString().toCharArray();
      for(char c:str)
      {
          if(hashtable[c]==)
              return c;
      }
      return '#';
    }
}

思路3:

同样使用哈希表,不过非常啊巧妙的借助队列

private int[] cnts = new int[];
private Queue<Character> queue = new LinkedList<>(); public void Insert(char ch)
{
cnts[ch]++;
queue.add(ch);
while (!queue.isEmpty() && cnts[queue.peek()] > )
queue.poll();
} public char FirstAppearingOnce()
{
return queue.isEmpty() ? '#' : queue.peek();
}

55.链表中环的入口节点

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

思路1:

设起点到相遇点距离为x,起点到入口点距离为y,环长度为r,则快慢针相遇时,满足2x-x=nr,n为快针在环中转的圈数。--> x=nr
快慢针相遇点距环入口点距离x-y
相遇后,快针从起点重新开始以步长为1速度开始走,经过距离y到达环入口点,慢针走y步后距离环入口点距离为x-y+y=x=nr,即走到了环入口点,两个指针相遇

public class Solution {
 
    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        ListNode fast = pHead;
        ListNode slow = pHead;
        while(fast !=null && fast.next !=null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                ListNode p = pHead;
                while( p != slow) {
                    p = p.next;
                    slow = slow.next;
                }
                return p;
            }
        }
        return null;
    }
}

思路2:

碉堡的解法:利用HashSet,遍历添加链表中的元素,若遇到重复添加则返回哪个元素。

import java.util.HashSet;
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
HashSet<ListNode> set = new HashSet<ListNode>();
while(pHead != null){
if(!set.add(pHead))
return pHead;
pHead = pHead.next;
}
return null;
}
}

使用ArrayList

List<ListNode> list = new ArrayList<ListNode>();
        while(!list.contains(pHead))
        {
            list.add(pHead);
            if(pHead.next!=null)
                pHead = pHead.next;
            else
                break;
        }
        if(pHead.next == null)return null;
        return pHead;

56.删除链表中重复的节点

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

1.递归方法(推荐)

public class Solution {
 public ListNode deleteDuplication(ListNode pHead) {
        if (pHead == null || pHead.next == null) { // 只有0个或1个结点,则返回
            return pHead;
        }
        if (pHead.val == pHead.next.val) { // 当前结点是重复结点
            ListNode pNode = pHead.next;
            while (pNode != null && pNode.val == pHead.val) {
                // 跳过值与当前结点相同的全部结点,找到第一个与当前结点不同的结点
                pNode = pNode.next;
            }
            return deleteDuplication(pNode); // 从第一个与当前结点不同的结点开始递归
        } else { // 当前结点不是重复结点
            pHead.next = deleteDuplication(pHead.next); // 保留当前结点,从下一个结点开始递归
            return pHead;
        }
    }
}

2.非递归方法:

public static ListNode deleteDuplication(ListNode pHead) {
         
        ListNode first = new ListNode(-);//设置一个trick
 
        first.next = pHead;
 
        ListNode p = pHead;
        ListNode last = first;
        while (p != null && p.next != null) {
            if (p.val == p.next.val) {
                int val = p.val;
                while (p!= null&&p.val == val)
                    p = p.next;
                last.next = p;
            } else {
                last = p;
                p = p.next;
            }
        }
        return first.next;
    }

57.二叉树的下一个节点

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

思路:

① 如果一个节点的右子树不为空,那么该节点的下一个节点是右子树的最左节点;

② 否则,向上找第一个左链接指向的树包含该节点的祖先节点。

/*
public class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null; TreeLinkNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
if(pNode.right !=null){
TreeLinkNode node = pNode.right;
while (node.left != null) //如果有右子树,则找右子树的最左节点
node = node.left;
return node;
}else{
while(pNode.next != null){
TreeLinkNode parent = pNode.next;
if(parent.left == pNode) //没右子树,则找第一个当前节点是父节点左孩子的节点
return parent;
pNode = pNode.next;
}
}
return null; //退到了根节点仍没找到,则返回null
}
}

58.对称的二叉树

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

思路:

1.递归算法

1).只要pRoot.left和pRoot.right是否对称
2).左右节点的值相等且对称子树left.left, right.right ;left.rigth,right.left也对称
3 ).注意要把null作为一个节点也考虑进去
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot == null)
return true;
return isSymmetrical(pRoot.left,pRoot.right);
} boolean isSymmetrical(TreeNode t1,TreeNode t2){
if(t1 == null && t2 == null)
return true;
if(t1 == null) return t2 == null;
if(t2 == null) return false;
if(t1.val != t2.val) return false;
return isSymmetrical(t1.left,t2.right) && isSymmetrical(t1.right,t2.left);
}
}

2.使用栈

使用stack来保存成对的节点

 1).出栈的时候也是成对成对的 ,
                1.若都为空,继续;
                2.一个为空,返回false;
                3.不为空,比较当前值,值不等,返回false;

2).确定入栈顺序,每次入栈都是成对成对的,如left.left, right.right ;left.rigth,right.left

boolean isSymmetricalDFS(TreeNode pRoot)
    {
        if(pRoot == null) return true;
        Stack<TreeNode> s = new Stack<>();
        s.push(pRoot.left);
        s.push(pRoot.right);
        while(!s.empty()) {
            TreeNode right = s.pop();//成对取出
            TreeNode left = s.pop();
            if(left == null && right == null) continue;
            if(left == null || right == null) return false;
            if(left.val != right.val) return false;
            //成对插入
            s.push(left.left);
            s.push(right.right);
            s.push(left.right);
            s.push(right.left);
        }
        return true;
    }

59.按照只字形顺序打印二叉树

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

重点学习:使用堆栈实现层级遍历,然后借助一个标记变量实现反向排序是之字形遍历。

每当使下一个层级的节点入堆栈,记录堆栈中节点的个数,然后取出相应个数的节点。

注意:堆栈中是可以存放null值的,当遍历到null时,直接返回,当null也全部从堆栈中弹出后堆栈为空就代表全部遍历完结束。

import java.util.ArrayList;

/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null; public TreeNode(int val) {
this.val = val; } }
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) { ArrayList<ArrayList<Integer>> al = new ArrayList<ArrayList<Integer>>();
Queue <TreeNode> q = new LinkedList<>();
q.add(pRoot);
boolean reverse = false;
while(!q.isEmpty()){
ArrayList<Integer> ll = new ArrayList<Integer>();
int cnt = q.size();
while(cnt-- > ){
TreeNode node = q.poll();
if(node == null)
continue;
ll.add(node.val);
q.add(node.left);
q.add(node.right);
}
if(reverse)
Collections.reverse(ll);
reverse = !reverse;
if(ll.size() != )
al.add(ll);
}
return al;
} }

60.把二叉树打印成多行

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

思路:跟前面那个类似,只是不用翻转顺序

import java.util.ArrayList;

/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null; public TreeNode(int val) {
this.val = val; } }
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.add(pRoot);
while (!queue.isEmpty()) {
ArrayList<Integer> list = new ArrayList<>();
int cnt = queue.size();
while (cnt-- > ) {
TreeNode node = queue.poll();
if (node == null)
continue;
list.add(node.val);
queue.add(node.left);
queue.add(node.right);
}
if (list.size() != )
ret.add(list);
}
return ret;
} }

61.序列化二叉树

请实现两个函数,分别用来序列化和反序列化二叉树

思路:

序列化:用前序遍历递归,递归的终止条件

if(root == null)
return "#";

反序列化:同样以前序遍历的书序递归构造

递归的终止条件

if(strr[index].equals("#"))
return null;

用一个位置变量index记录遍历到达的位置

public class Solution {

   private int index = -;
String Serialize(TreeNode root) {
if(root == null)
return "#";
return root.val +" "+ Serialize(root.left)+" " + Serialize(root.right);
} TreeNode Deserialize(String str) {
  index++;
        String[] strr = str.split(" "); if(strr[index].equals("#"))
return null;
        TreeNode  node = new TreeNode(Integer.valueOf(strr[index]));
        node.left = Deserialize(str);
        node.right = Deserialize(str);
         
        return node; }
}

遍历的时候传入未遍历到不同的字符串

private String deserializeStr;

public String Serialize(TreeNode root)
{
if (root == null)
return "#";
return root.val + " " + Serialize(root.left) + " " + Serialize(root.right);
} public TreeNode Deserialize(String str)
{
deserializeStr = str;
return Deserialize();
} private TreeNode Deserialize()
{
if (deserializeStr.length() == )
return null;
int index = deserializeStr.indexOf(" ");
String node = index == - ? deserializeStr : deserializeStr.substring(, index);
deserializeStr = index == - ? "" : deserializeStr.substring(index + );
if (node.equals("#"))
return null;
int val = Integer.valueOf(node);
TreeNode t = new TreeNode(val);
t.left = Deserialize();
t.right = Deserialize();
return t;
}

62.二叉搜索树的第k个节点

给定一颗二叉搜索树,请找出其中的第k小的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。

思路:利用二叉搜索数中序遍历有序的特点,递归的中序遍历第k个节点就是。

public class Solution {

     private TreeNode ret =null;
private int cnt = ;
TreeNode KthNode(TreeNode pRoot, int k)
{
inorder(pRoot,k);
return ret;
} void inorder(TreeNode pRoot, int k){
if(pRoot == null || cnt > k)
return;
inorder(pRoot.left,k);
cnt++;
if(cnt == k)
ret = pRoot;
inorder(pRoot.right,k);
} }

63.数据流中的中位数

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

思路:

将数据流分成了两个部分,从中间切分(想象一下数据流有序时的样子),大顶堆里面是小的一半,小顶堆大的一半,当求中位数时只用关心中间的一个数或者两个数,这时关心的数就是堆顶的数

import java.util.PriorityQueue;
public class Solution { private int count = ;
private PriorityQueue<Integer> max = new PriorityQueue<Integer>((o1,o2)->(o2-o1));
private PriorityQueue<Integer> min = new PriorityQueue<Integer>();
public void Insert(Integer num) {
if(count% ==){
//当数据总数为偶数时,新加入的元素,应当进入小根堆
        //(注意不是直接进入小根堆,而是经大根堆筛选后取大根堆中最大元素进入小根堆)
        //1.新加入的元素先入到大根堆,由大根堆筛选出堆中最大的元素
max.add(num);
//2.筛选后的【大根堆中的最大元素】进入小根堆
min.add(max.poll());
}else {
//当数据总数为奇数时,新加入的元素,应当进入大根堆
        //(注意不是直接进入大根堆,而是经小根堆筛选后取小根堆中最大元素进入大根堆)
        //1.新加入的元素先入到小根堆,由小根堆筛选出堆中最小的元素
min.add(num);
//2.筛选后的【小根堆中的最小元素】进入大根堆
max.add(min.poll());
}
count++;
} public Double GetMedian() {
if(count% ==)
return (min.peek()+max.peek())/2.0;
else
return (double)min.peek();
} }

64.滑动窗口的最大值

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

思路1:朴素的解法:

import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> al = new ArrayList<>();
if(num.length == || size==)
return al;
for(int i = ; i<num.length-size+;i++){
int [] a = new int[size];
for(int j=;j<size;j++){
a[j] = num[i+j];
}
al.add(max(a));
}
return al;
} public Integer max(int[] num){
int max = num[];
for(int i = ;i<num.length;i++){
if(num[i]>max)
max = num[i];
}
return max;
} }

思路2:大顶堆解法

public ArrayList<Integer> maxInWindows(int[] num, int size)
{
ArrayList<Integer> ret = new ArrayList<>();
if (size > num.length || size < )
return ret;
PriorityQueue<Integer> heap = new PriorityQueue<>((o1, o2) -> o2 - o1); /* 大顶堆 */
for (int i = ; i < size; i++)
heap.add(num[i]);
ret.add(heap.peek());
for (int i = , j = i + size - ; j < num.length; i++, j++) { /* 维护一个大小为 size 的大顶堆 */
heap.remove(num[i - ]);
heap.add(num[j]);
ret.add(heap.peek());
}
return ret;
}

65.矩阵中的路径

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

思路:回溯算法,回溯的思想体现在体现在那个很长的if语句后面的,flag标记的恢复

public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
int flag[] = new int[matrix.length];
for (int i = ; i < rows; i++) {
for (int j = ; j < cols; j++) {
if (helper(matrix, rows, cols, i, j, str, , flag))
return true;
}
}
return false;
} private boolean helper(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, int[] flag) {
int index = i * cols + j;
if (i < || i >= rows || j < || j >= cols || matrix[index] != str[k] || flag[index] == )
return false;
if(k == str.length - ) return true;
flag[index] = ;
if (helper(matrix, rows, cols, i - , j, str, k + , flag)
|| helper(matrix, rows, cols, i + , j, str, k + , flag)
|| helper(matrix, rows, cols, i, j - , str, k + , flag)
|| helper(matrix, rows, cols, i, j + , str, k + , flag)) {
return true;
}
flag[index] = ;
return false;
} }

66.机器人的运动范围

地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

思路:从0,0开始通过递归遍历上下左右加起来的结果就是最大的连通区域

public class Solution {
public int movingCount(int threshold, int rows, int cols) {
int flag[][] = new int[rows][cols]; //记录是否已经走过
return helper(, , rows, cols, flag, threshold);
} private int helper(int i, int j, int rows, int cols, int[][] flag, int threshold) {
if (i < || i >= rows || j < || j >= cols || numSum(i) + numSum(j) > threshold || flag[i][j] == ) return ;
flag[i][j] = ;
return helper(i - , j, rows, cols, flag, threshold)
+ helper(i + , j, rows, cols, flag, threshold)
+ helper(i, j - , rows, cols, flag, threshold)
+ helper(i, j + , rows, cols, flag, threshold)
+ ;
} private int numSum(int i) {
int sum = ;
do{
sum += i%;
}while((i = i/) > );
return sum;
}
}

剑指offer编程题66道题 36-66的更多相关文章

  1. 剑指Offer编程题2——替换空格

    剑指Offer编程题2——替换空格 题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happ ...

  2. 剑指Offer编程题1——二维数组中的查找

    剑指Offer编程题1---------------二维数组中的查找 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完 ...

  3. 剑指offer编程题Java实现——面试题12打印1到最大的n位数

    题目:打印1到最大的n位数 输入数字n,按顺序打印输出从1到最大的n位十进制数,比如输入3,打印从1到999. 这道题考察的地方是如何表示大数问题.由于n是任意大的数组,如果n太大的话n位数就超过了l ...

  4. 剑指offer编程题Java实现——面试题12相关题大数的加法、减法、乘法问题的实现

    用字符串或者数组表示大数是一种很简单有效的表示方式.在打印1到最大的n为数的问题上采用的是使用数组表示大数的方式.在相关题实现任意两个整数的加法.减法.乘法的实现中,采用字符串对大数进行表示,不过在具 ...

  5. 剑指offer编程题Java实现——替换空格

    题目描述 请实现一个函数,将一个字符串中的空格替换成"%20".例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. package ...

  6. 剑指offer编程题Java实现——面试题5从头到尾打印链表

    题目描述* 剑指offer面试题5:从尾到头打印链表 输入一个链表的头结点,从尾到头打印出每个结点的值 解决方案一:首先遍历链表的节点后打印,典型的"后进先出",可以使用栈来实现这 ...

  7. 剑指offer编程题Java实现——面试题6重建二叉树

    题目: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2, ...

  8. 剑指offer编程题Java实现——面试题11数值的整数次方

    题目: 实现函数double power(double base,int exponent),求base的exponent次方.不得使用库函数,同时不需要考虑大数问题. 解题思路:最一般的方法实现数值 ...

  9. 剑指offer编程题Java实现——面试题14调整数组顺序使奇数位于偶数之前

    题目: 输入一个整数数组,实现一个函数来调整该数组中数组的顺序,使得所有的奇数位于数组的前半部分,偶数位于数组的后半部分. 解题思路:数组中维护两个指针,第一个指针初始化时候指向数组头部,第二个指针初 ...

随机推荐

  1. mac os下android 通过battery-historian进行电量分析

    简单介绍下如何用battery-historian进行电量分析,因为battery-hostorian是基于go语言的框架,所以需要安装go 1.安装go 2.配置go环境变量到.bash_profi ...

  2. cobbler default system 网络安装时主机的menu上只有一个local选项

    问题:使用cobbler default system 做pxe网络安装时,主机启动后安装menu上只有一个local选项,看不到对应的system名字 解决:cobbler default syst ...

  3. cobbler setting dnsmasq

    Currently cobbler can help generate a ISC DHCP configuration (package name: dhcpd) it can also alter ...

  4. Codeforces Round #210 (Div. 1).B

    经典的一道DP题. 题目明显是一道DP题,但是比赛的时候一个劲就在想怎么记录状态和转移.最后想到了一种n^3的方法,写了下,不出所料的超时了. 看了别人的代码才发现竟然是先二分然后再进行DP,像这种思 ...

  5. storyboard设置navigation controller

    到storyboard选中我们唯一一个的viewcontroller,找到xcode的菜单栏,Edit->Embed In->NavigationController.这时候storybo ...

  6. ES6通过WeakMap解决内存泄漏问题

    一.Map 1.定义 Map对象保存键值对,类似于数据结构字典:与传统上的对象只能用字符串当键不同,Map对象可以使用任意值当键. 2.语法 new Map([iterable]) 属性 size:返 ...

  7. OVN实战---《A Primer on OVN》翻译

    overview 在本文中,我们将在三个host之间创建一个简单的二层overlay network.首先,我们来简单看一下,整个系统是怎么工作的.OVN基于分布式的control plane,其中各 ...

  8. 如何让socket编程非阻塞?

    import socket # 创建socket client = socket.socket() # 将原来阻塞的位置变成非阻塞(报错) client.setblocking(False) # 百度 ...

  9. qt下通过socket传送中文

    zz 1.在main函数里我之前就加了一句QTextCodec::setCodecForTr( QTextCodec::codecForLocale() ); 现在再加一句QTextCodec::se ...

  10. C# 调用win api获取chrome浏览器中地址

    //FindWindow 查找窗口 //FindWindowEx查找子窗口 //EnumWindows列举屏幕上的所有顶层窗口,如果回调函数成功则返回非零,失败则返回零 //GetWindowText ...