14th Feb: Why BB? Valentine's Gift

来源:互联网 发布:json 查找 编辑:程序博客网 时间:2024/05/21 19:48

数学题:


1)Sqrt(x)


Implement int sqrt(int x).


Compute and return the square root of x.


这道题是一道采用二分思想的题。由于题目返回的是int,所以我们需要做的是寻找一个int 的平方最接近x。这时候需要使用二分法,确定两个数,相差1。如果后一个数的平方小于x,就是后一个数。否则是前一个数。


代码:


public class Solution {    public int mySqrt(int x) {        if (x < 0) {            return -1;        }                if (x == 0 || x == 1) {            return x;        }                long start = 1;        long end = x;                long mid = (start + end) / 2;        long tmp = mid * mid;                while (start + 1 < end) {            if (tmp < x) {                start = mid;            } else {                end = mid;            }            mid = (start + end) / 2;            tmp = mid * mid;        }                if (end * end <= x) {            return (int)end;        }                return (int)start;    }}

2) Pow(x,n)


这道题主要思考清楚n是负数的情况,以及n = 1或者n = 0的时候就可以直接返回。剩下的不难,直接实现的代码:


public class Solution {    public double myPow(double x, int n) {        if (n == 0) {            return 1;        }                if (n == 1) {            return x;        }                boolean isNeg = false;                if (n < 0) {            isNeg = true;            n = -n;        }                double ans = 1;                for (int i = 0; i < n; i++) {            ans *= x;        }                if (isNeg) {            ans = 1 / ans;        }                 return ans;    }}

但是,这么做遇到了time limit excess的问题,所以再次考虑使用Divide and Conquer 的递归操作:


public class Solution {    public double myPow(double x, int n) {        if (n == 0) {            return 1;        }                if (n == 1) {            return x;        }                boolean isNeg = false;                if (n < 0) {            isNeg = true;            n = -n;        }                double ans = (n % 2) == 0 ? myPow(x * x, n / 2) : x * myPow(x * x, n / 2);                if (isNeg) {            ans = 1 / ans;        }                 return ans;    }}


但是上述的程序还是没有考虑到一个corner case: 万一n是 2^-31次方,直接去相反数就导致溢出。所以,要直接把 n = (2 ^ 31 - 1) -1,为什么要减1?因为要保持奇偶性质。所以,真正通过的程序是:


public class Solution {    public double myPow(double x, int n) {        if (n == 0) {            return 1;        }                if (n == 1) {            return x;        }                if (n < 0) {            x = 1 / x;            if (n == Integer.MIN_VALUE) {                n = Integer.MAX_VALUE - 1;            } else {                n = -n;            }        }                double ans = (n % 2 == 0) ? myPow(x * x, n / 2) : x * myPow(x * x, n / 2);                return ans;    }}

DFS回溯题:


386. Lexicographical Numbers


Given an integer n, return 1 - n in lexicographical order.


For example, given 13, return: [1,10,11,12,13,2,3,4,5,6,7,8,9].


Please optimize your algorithm to use less time and space. The input size may be as large as 5,000,000.


public class Solution {    private void dFS(int cur, int n, List<Integer> ans) {        if (cur > n) {            return;        }                ans.add(cur);        for (int i = 0; i < 10; i++) {            int tmp = cur * 10 + i;            dFS(tmp, n, ans);        }    }        public List<Integer> lexicalOrder(int n) {        if (n < 1) {            return null;        }                List<Integer> ans = new ArrayList<Integer>();                for (int i = 1; i < 10; i++) {            dFS(i, n, ans);        }                return ans;    }}



贪心算法题:


122. Best Time to Buy and Sell Stock II


Say you have an array for which the ith element is the price of a given stock on day i.


Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).


这道题需要利用一个性质,在代码的注释里提到了。所以,只要是递增的相邻对,就把价差算进Profit里面。


public class Solution {    public int maxProfit(int[] prices) {        if (prices == null || prices.length < 2) {            return 0;        }                int res = 0;                         /* 逻辑是找出递增的所有相邻对,每次找到递增,计算profit加到结果当中。例如:[1,2,3],1买,2卖,2再买,3再卖。和1买3卖的         profit是一样的*/                for (int i = 0; i < prices.length - 1; i++) {            if (prices[i] < prices[i + 1]) {                res += (prices[i + 1] - prices[i]);            }        }            return res;    }}


Missing Number: 


Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.


For example,
Given nums = [0, 1, 3] return 2.


Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?


最简单做法:复杂度 O(nlogn)


public class Solution {    public int missingNumber(int[] nums) {        Arrays.sort(nums);                for (int i = 0; i < nums.length; i++) {            if (nums[i] != i) {                return i;            }        }                return nums.length;    }}

位操作做法:利用如果有两个相同的数异或的话会相互抵消。在这里最基础的假设也是ans = nums.length. 


复杂度:O(n)


public class Solution {    public int missingNumber(int[] nums) {        int ans = nums.length;                for (int i = 0; i < nums.length; i++) {            ans ^= nums[i];            ans ^= i;        }                return ans;    }}

求和做法:

复杂度:O(n)

public class Solution {    public int missingNumber(int[] nums) {        int sum = (0 + nums.length) * (1 + nums.length) / 2;                for (int tmp : nums) {            sum = sum - tmp;        }                return sum;    }}


Reverse Integer:


Reverse digits of an integer.


Example1: x = 123, return 321
Example2: x = -123, return -321


click to show spoilers.


Note:

The input is assumed to be a 32-bit signed integer. Your function should return 0 when the reversed integer overflows.


最简单的方法就是用一个栈去实现(注意负数的时候把它转换为正数再求余,因为负数求余不好控制。同时,当是最小的负数的时候,extreme case需要特殊考虑):


public class Solution {    public int reverse(int x) {        boolean isNeg = false;                if (x < 0) {           isNeg = true;            x = -x;        }                if (x == Integer.MIN_VALUE) {            return 0;        }                LinkedList<Integer> stack = new LinkedList<Integer>();                int tmp = x;        while (tmp != 0) {            int bit = tmp % 10;            tmp = tmp / 10;                        stack.addFirst(bit);        }                int oriSize = stack.size();        int ans = 0;                while (!(stack.isEmpty())) {            double temp = stack.removeFirst() * Math.pow(10, oriSize - stack.size() - 1);            if (ans + temp > Integer.MAX_VALUE) {                return 0;            } else {                ans += temp;            }        }                if (isNeg) {            ans = -ans;        }                return ans;    }}

直接使用O(1)的空间复杂度:


public class Solution {    public int reverse(int x) {        int ans = 0;        int tmp = x;                while (tmp != 0) {            int tmpRes = ans * 10 + (tmp % 10);            tmp = tmp / 10;                        if ((tmpRes / 10) != ans) {                ans = 0;                break;            }                        ans = tmpRes;         }                return ans;    }}


注意中间求出来的结果不要直接更新ans,要先看看有没有溢出。


Validate Binary Search Tree


Given a binary tree, determine if it is a valid binary search tree (BST).


Assume a BST is defined as follows:


The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than the node's key.
Both the left and right subtrees must also be binary search trees.
Example 1:
    2
   / \
  1   3
Binary tree [2,1,3], return true.
Example 2:
    1
   / \
  2   3
Binary tree [1,2,3], return false.


这一题,第一印象就是按照三个判断条件写出来的递归:


/** * Definition for a binary tree node. * public class TreeNode { *     int val; *     TreeNode left; *     TreeNode right; *     TreeNode(int x) { val = x; } * } */public class Solution {    public boolean isValidBST(TreeNode root) {        if (root == null) {            return true;        }                boolean left = isValidBST(root.left);        boolean right = isValidBST(root.right);                if (left && right && ((root.left == null) || (root.left.val < root.val)) && (root.right == null || (root.right.val > root.val))) {            return true;        } else {            return false;        }    }}

这样的算法能通过大部分的test case,但是一种非BST会通过这个算法法眼。如果不是当前层的两个孩子的值违反规则,而是孩子的孩子有值违反规则。这个算法是无法


换个角度想,如果每次都要父亲去关心自己的后代是否有比自己小的,还不如让每个后代主动观察自己是否比父亲小,这个方法就巧妙方便多了:


public class Solution {    public boolean isValidBST(TreeNode root) {        return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);    }        public boolean isValidBST(TreeNode root, long minVal, long maxVal) {        if (root == null) return true;        if (root.val >= maxVal || root.val <= minVal) return false;        return isValidBST(root.left, minVal, root.val) && isValidBST(root.right, root.val, maxVal);    }}


Reverse Words in a String


Given an input string, reverse the string word by word.


For example,
Given s = "the sky is blue",
return "blue is sky the".


注意这道题需要clarify 一些事情:


What constitutes a word?
A sequence of non-space characters constitutes a word.


Could the input string contain leading or trailing spaces?
Yes. However, your reversed string should not contain leading or trailing spaces.


How about multiple spaces between two words?
Reduce them to a single space in the reversed string.


使用栈实现的反转O(1)空间复杂,O(n)时间复杂


public class Solution {    public String reverseWords(String s) {        s = s.trim();                if (s == null || s.length() == 0 || s.length() == 1) {            return s;        }                String[] tmp = s.split(" +");        LinkedList<String> stack = new LinkedList<String>();                for (String ins : tmp) {            stack.addFirst(ins);        }                String returnStr = "";                while (stack.size() > 1) {            returnStr += stack.removeFirst() + " ";        }                if (stack.size() == 1) {            returnStr += stack.removeFirst();        }                return returnStr;    }}

如果想使用O(1)的空间复杂度呢?


public class Solution {    public String reverseWords(String s) {        if (s == null) {            return null;        }                s = s.trim();                if (s.length() == 0 || s.length() == 1) {            return s;        }                String res = "";                String[] tmp = s.split(" +");                for (int i = tmp.length - 1; i > 0; i--) {            res += tmp[i] + " ";        }                res += tmp[0];                return res;    }}

这道题的注意点在于构造完答案的最后,不能带有空格。


Remove Duplicates from Sorted Array


Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.


Do not allocate extra space for another array, you must do this in place with constant memory.


For example,
Given input array nums = [1,1,2],


Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. It doesn't matter what you leave beyond the new length.


两指针做法:


public class Solution {    public int removeDuplicates(int[] nums) {        if (nums == null) {            return 0;        }                if (nums.length < 2) {            return nums.length;        }                int firstP = 0;        int secP = 1;                while (secP < nums.length) {            if (nums[firstP] == nums[secP]) {                nums[firstP] = nums[secP++];            } else {                nums[++firstP] = nums[secP++];            }        }                return firstP + 1;    }}


Same Tree


Given two binary trees, write a function to check if they are equal or not.


Two binary trees are considered equal if they are structurally identical and the nodes have the same value.


DFS递归:


/** * Definition for a binary tree node. * public class TreeNode { *     int val; *     TreeNode left; *     TreeNode right; *     TreeNode(int x) { val = x; } * } */public class Solution {    public boolean isSameTree(TreeNode p, TreeNode q) {        if (p == null && q == null) {            return true;        }                 if (p == null || q == null) {            return false;        }                boolean left = isSameTree(p.left, q.left);        boolean right = isSameTree(p.right, q.right);                if (left && right && (p.val == q.val)) {            return true;        } else {            return false;        }    }}

非递归的别人的答案:


public boolean isSameTree(TreeNode p, TreeNode q) {     Stack<TreeNode> stack_p = new Stack <> ();            Stack<TreeNode> stack_q = new Stack <> ();     if (p != null) stack_p.push( p ) ;     if (q != null) stack_q.push( q ) ;     while (!stack_p.isEmpty() && !stack_q.isEmpty()) {     TreeNode pn = stack_p.pop() ;     TreeNode qn = stack_q.pop() ;         if (pn.val != qn.val) return false ;     if (pn.right != null) stack_p.push(pn.right) ;     if (qn.right != null) stack_q.push(qn.right) ;     if (stack_p.size() != stack_q.size()) return false ;     if (pn.left != null) stack_p.push(pn.left) ;               if (qn.left != null) stack_q.push(qn.left) ;     if (stack_p.size() != stack_q.size()) return false ;     }          return stack_p.size() == stack_q.size() ;  }


113. Path Sum II


Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.


For example:
Given the below binary tree and sum = 22,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1
return
[
   [5,4,11,2],
   [5,8,4,5]
]


/** * Definition for a binary tree node. * public class TreeNode { *     int val; *     TreeNode left; *     TreeNode right; *     TreeNode(int x) { val = x; } * } */public class Solution {    private int getSum (List<Integer> input) {        int sum = 0;                if (input == null || input.size() == 0) {            return sum;        }                for (int tmp : input) {            sum += tmp;        }                return sum;    }        private void recursive(TreeNode root, int sum, List<List<Integer>> ans, List<Integer> tmp) {        if (root == null) {            return;        }                    tmp.add(root.val);        if (root.left == null && root.right == null && getSum(tmp) == sum) {            ans.add(new ArrayList<Integer>(tmp));            tmp.remove(tmp.size() - 1);            return;        } else {            recursive(root.left, sum, ans, tmp);            recursive(root.right, sum, ans, tmp);            tmp.remove(tmp.size() - 1);        }    }        public List<List<Integer>> pathSum(TreeNode root, int sum) {        List<List<Integer>> ans = new ArrayList<List<Integer>>();                recursive(root, sum, ans, new ArrayList<Integer>());                return ans;    }}


复杂度分析:


每次递归的操作都是O(1)的操作完成的,因为add和remove都是O(1), remove最后一个嘛。所以整体的复杂度是:有n个点,复杂度就是O(n)。


Roman to Integer (死记硬背题)


Given a roman numeral, convert it to an integer.


Input is guaranteed to be within the range from 1 to 3999.


public class Solution {    public int romanToInt(String s) {        int nums[]=new int[s.length()];        for(int i=0;i<s.length();i++){            switch (s.charAt(i)){                case 'M':                    nums[i]=1000;                    break;                case 'D':                    nums[i]=500;                    break;                case 'C':                    nums[i]=100;                    break;                case 'L':                    nums[i]=50;                    break;                case 'X' :                    nums[i]=10;                    break;                case 'V':                    nums[i]=5;                    break;                case 'I':                    nums[i]=1;                    break;            }        }        int sum=0;        for(int i=0;i<nums.length-1;i++){            if(nums[i]<nums[i+1])                sum-=nums[i];            else                sum+=nums[i];        }        return sum+nums[nums.length-1];    }}





0 0
原创粉丝点击