zoukankan      html  css  js  c++  java
  • 剑指offer 第十天

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

    统计一个数字在排序数组中出现的次数。
    采用二分查找法

    /*
    方法一:时间复杂度O(n),不可选
    */
    
    public class Solution {
        public int GetNumberOfK(int [] array , int k) {
            if(array.length == 0) return 0;
            int count = 0;
            for(int i = 0 ; i < array.length ; i++){
                if(array[i] == k){
                    count++;
                }else{
                    if(count != 0)
                        break;
                }
            }
            return count;
        }
    }
    
    /*
    方法二:首选!先采用二分查找法,在数组中查找到第一个K和第二个K,总时间复杂度O(logn)
    */
    public class Solution {
        public int GetNumberOfK(int[] array,int k){
            if(array.length == 0) return 0;
            int first = getFirstK(array,k,0,array.length-1);
            int last = getLastK(array,k,0,array.length-1);
            if(first > -1 && last > -1)
                return last - first + 1;
            return 0;
        }
        public int getFirstK(int[] array,int k,int start,int end){
            if(start > end) return -1;
            int midIdx = (end + start)/2;
            if(array[midIdx] == k){
                if((midIdx > 0 && array[midIdx-1] != k) || midIdx == 0)
                    return midIdx;
                else{
                    end = midIdx - 1;
                    return getFirstK(array,k,start,end);
                }
            }else if(array[midIdx] > k){
                end = midIdx - 1;
            }else if(array[midIdx] < k){
                start = midIdx +1;
            }
            return getFirstK(array,k,start,end);
        }
        public int getLastK(int[] array,int k ,int start,int end){
            if(start > end) return -1;
            int midIdx = (start + end)/2;
            if(array[midIdx] == k){
                if((midIdx < array.length-1 && array[midIdx+1] != k) || midIdx == array.length-1)
                    return midIdx;
                else
                    start = midIdx + 1;
            }else if(array[midIdx] > k){
                end = midIdx - 1;
            }else if(array[midIdx] < k){
                start = midIdx + 1;
            }
            return getLastK(array,k,start,end);
        }
    }
    
    
    

    38.二叉树的深度

    输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

    /**
    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 0;
            int left = TreeDepth(root.left);
            int right = TreeDepth(root.right);
            if(left>right) return left+1;
            else return right+1;
        }
    }
    

    39.平衡二叉树

    输入一棵二叉树,判断该二叉树是否是平衡二叉树。如果某二叉树中任意节点的左、右子树的深度相差不超过1,那么他就是一棵平衡二叉树。
    解法一:不够简便

    public class Solution {
        public boolean IsBalanced_Solution(TreeNode root) {
            if(root == null) return true;
            int left = TreeDepth(root.left);
            int right = TreeDepth(root.right);
            if((left-right)>1||(left-right)<-1)
                return false;
            else
                return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
        }
        public int TreeDepth(TreeNode root){
            if(root == null) return 0;
            int left = TreeDepth(root.left);
            int right = TreeDepth(root.right);
            return left > right ? left+1 : right+1;
        }
    }
    

    解法二:推荐!后序遍历二叉树,只需遍历一遍即可。

    public class Solution {
        public boolean IsBalanced_Solution(TreeNode root) {
            return getDepth(root) != -1;
        }
        public int getDepth(TreeNode root){
            if(root == null) return 0;
            int left = getDepth(root.left);
            if(left == -1)
                return -1;
            int right = getDepth(root.right);
            if(right == -1)
                return -1;
            return Math.abs(left-right) > 1 ? -1 : Math.max(left,right) + 1;
        }
    }
    

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

    一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
    第一种:利用Set,空间复杂度为O(N)

    //num1,num2分别为长度为1的数组。传出参数
    //将num1[0],num2[0]设置为返回结果
    import java.util.HashSet;
    import java.util.Iterator;
    public class Solution {
        public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
            HashSet<Integer> set = new HashSet<Integer>();
            for(int i = 0;i<array.length;i++){
                if(set.contains(array[i])){
                    set.remove(array[i]);
                }else{
                    set.add(array[i]);
                }
            }
            boolean isFirst = true;
            Iterator iter = set.iterator();
            while(iter.hasNext()){
                if(isFirst){
                    num1[0] = (int)iter.next();
                    isFirst = false;
                }else
                    num2[0] = (int)iter.next();
            }
        }
    }
    

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

    一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
    按位运算:异或、位移

    //num1,num2分别为长度为1的数组。传出参数
    //将num1[0],num2[0]设置为返回结果
    public class Solution {
        public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
            int OR = 0;
            for(int i = 0;i<array.length;i++)
                OR ^= array[i];
            int idx = 0;//OR从后数第几位是1,从1开始
            while(OR != 0){
                OR = OR >> 1;
                idx++;
            }
            num1[0] = 0;
            num2[0] = 0;
            for(int i = 0;i<array.length;i++){
                if((array[i]&(1<<(idx-1))) == 0)
                    num1[0] ^= array[i];
                else
                    num2[0] ^= array[i];
            }
        }
    }
    

    42.和为S的连续正数序列

    小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
    输出描述:
    输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序

    import java.util.ArrayList;
    public class Solution {
        public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
            ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
            int small = 1,big = 2,listSum = 3;
            int mid = (sum+1)/2;
            while(small < mid && small < big){
                if(listSum == sum){ //注意此处很容易出现死循环,当检测出一个序列后,记得变化small数值
                    ArrayList<Integer> listResult = new ArrayList<>();
                    for(int i = small;i <= big;i++)
                        listResult.add(i);
                    result.add(listResult);
                    listSum -= small;
                    small++;
                }else if(listSum < sum){
                    big++;
                    listSum += big;
                }else if(listSum > sum){
                    listSum -= small;
                    small++;
                }
            }
            return result;
        }
    }
    

    43.和为S的两个数

    输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
    解析:
    其实找的就是数组最两侧满足和为S的数字,因为:

    z=xy

    x+y=s

    z=x(s-x)=sx-x^2 函数图像为向下开口的抛物线,两段数值小中间大。所以取两边的值。

    import java.util.ArrayList;
    public class Solution {
        public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
            ArrayList<Integer> result = new ArrayList<>();
            int p1 = 0,p2 = array.length-1;
            while(p1<p2){
                if(array[p1]+array[p2] == sum){
                    result.add(array[p1]);
                    result.add(array[p2]);
                    return result;
                }else if(array[p1]+array[p2]>sum)
                    p2--;
                else
                    p1++;
            }
            return result;
        }
    }
    

    44.坐旋转字符串

    汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
    该题有好多种做法
    方法一:虽然AC,但是不是最优解

    public class Solution {
        public String LeftRotateString(String str,int n) {
            if(n<0 || str==null || str.length() == 0) return "";
            n %= str.length();
            StringBuilder sb = new StringBuilder();
            for(int i = n;i<str.length();i++){
                sb.append(str.charAt(i));
            }
            for(int i = 0;i<n;i++){
                sb.append(str.charAt(i));
            }
            return sb.toString();
        }
    }
    

    方法二

    public class Solution {
        public String LeftRotateString(String str,int n) {
            if(n<0 || str==null || str.length() == 0) return "";
            n %= str.length();
            StringBuilder sb = new StringBuilder();
            for(int i = n;i<str.length();i++){
                sb.append(str.charAt(i));
            }
            for(int i = 0;i<n;i++){
                sb.append(str.charAt(i));
            }
            return sb.toString();
        }
    }
    

    45.翻转字符串

    牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

    public class Solution {
        public String ReverseSentence(String str) {
            if(str.length()==0) return "";
            char[] charArray = str.toCharArray();
            Reverse(charArray,0,str.length()-1);
            int start = 0,end = 0;
            for(int i = 0;i < charArray.length;i++){
                if(charArray[i] == ' '){
                    end = i-1;
                    Reverse(charArray,start,end);
                    start = i+1;
                }
            }
            Reverse(charArray,start,charArray.length-1);
            return String.valueOf(charArray);
        }
        public char[] Reverse(char[] charArray,int start,int end){
            while(start<end){
                char temp = charArray[start];
                charArray[start] = charArray[end];
                charArray[end] = temp;
                start++;
                end--;
            }
            return charArray;
        }
    }
    
  • 相关阅读:
    Higher-Order Functions and Lambdas
    dispatch_sync:As an optimization, this function invokes the block on the current thread when possible
    为什么使用dispatch_sync
    如何安全使用dispatch_sync
    dispatch_sync
    Dispatch Queues and Thread Safety
    高阶函数-参数与返回值
    In Swift, typedef is called typealias:
    偏函数应用(Partial Application)和函数柯里化(Currying)
    Centos下添加用户到用户组
  • 原文地址:https://www.cnblogs.com/guoyaohua/p/8530492.html
Copyright © 2011-2022 走看看