转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6415011.html
16:Invert Binary Tree
此题:以根为对称轴,反转二叉树。
思路:看到二叉树,我们第一时间要想到处理二叉树的常用方法——BFS、DFS,更常用的是DFS。此题我们先用BFS来思考:BFS是逐层每个结点处理,即通过交换每层结点的位置来达到整体交换。我们可以用队列+栈来实现,用队列处理实现按层遍历,用栈实现当前层结点位置倒转,然后从根结点开始,逐层重新建树。无疑,这很麻烦。我们转而思考DFS怎么做:从根结点开始,交换左右子树,然后递归到下一层,交换左右子树......直到倒数第二层,交换左右子树,从而实现整体互换。
牢记DFS三步骤:递归边界返回值、当前层值由递归得出、递归的返回值是什么
public TreeNode invertTree(TreeNode root) {
//递归边界的返回值(dfs最容易出错的地方就在于边界的判断。忽略了边界为空的话很容易就报NullPointerException异常了)
if (root==null) {return null;}
//当前层处理:值由递归得到
TreeNode left=root.left;
TreeNode right=root.right;
root.left=invertTree(right);
root.right=invertTree(left);
//递归的返回值
return root;
}
17:Construct the Rectangle
1. The area of the rectangular web page you designed must equal to the given target area.
2. The width W should not be larger than the length L, which means L >= W.
3. The difference between length L and width W should be as small as possible.
Note:
- The given area won't exceed 10,000,000 and is a positive integer
此题:给出矩形面积area,求组成该面积的矩形的长和宽并且长宽尽可能接近。
思路:此题提示面积上限到了10000000,说明如果想暴力尝试求出该面积的所有长宽方式再取最接近者可能会超时。所以我们需要从最快的方法去找:观察得,一个数拆分成两数相乘形式并且因数接近的话,刚好开根号得到整数是最接近的,相差为0.比如area=4,则长=宽=2。但对于二次方根不为整数的情况,比如6,则长=3,宽=2,而 根号6=2.44。可以发现,长宽最接近并且相乘得面积的答案,长位于面积的方根的右边,宽位于方根的左边,并且是众多答案中最靠近方根的。由此,我们可得到解题思路:首先对面积开方根并向下取整,然后方根相乘,如果是面积则说明矩形是正方形,长宽为方根;如果方根相乘不等于面积,说明矩形不是正方形,由于我们向下取整求的方根,说明此时的方根在真实方根的左边,令width=方根,width逐步减小1,用area%width==0这个条件求出最接近的方根的并且能被面积整除的宽,然后area/width就是最接近方根的长了。
public int[] constructRectangle(int area) {
int[] res = null;
//向下取整求方根
int width=(int) Math.sqrt(area);
//方根相乘为面积则长宽为方根
if (width*width==area) {
return res=new int[]{width,width};
}
//否则,从方根开始减小,找到最接近方根的能被面积整除的宽
while(area%width!=0){
--width;
}
//由宽得长
int length=area/width;
return res=new int[]{length,width};
}
18:Relative Ranks
Given scores of N athletes, find their relative ranks and the people with the top three highest scores, who will be awarded medals: "Gold Medal", "Silver Medal" and "Bronze Medal".All the scores of athletes are guaranteed to be unique.
此题:给出N个运动员的比赛成绩,找出这N个运动员的相对名词,并且前三的用"Gold Medal", "Silver Medal" and "Bronze Medal"表示,其余名次则直接输出名次即可。
思路:映射类题目——根据比分映射为名次。第一时间想到map。
public String[] findRelativeRanks(int[] nums) {
//在对原数组排序前要先把内容赋值到另一个数组中保存。这里不能用old=nums:Java中数组是引用类对象,相当于C++中的指针,这样其实是把nums的指针给了old,没有起到内容复制保存起来的效果
int[] old=Arrays.copyOf(nums, nums.length);
Arrays.sort(nums);
Map<Integer, String> map=new HashMap<Integer, String>();
for (int i = 0;i<=nums.length-1;++i) {
if(i==nums.length-1){
map.put(nums[i], "Gold Medal");
}else if(i==nums.length-2){
map.put(nums[nums.length-2], "Silver Medal");
}else if(i==nums.length-3){
map.put(nums[nums.length-3], "Bronze Medal");
}else{
map.put(nums[nums.length-4-i], ""+(4+i));
}
}
String[] res=new String[nums.length];
//根据前面保存起来的旧内容,依次赋予排名
for(int i=0;i<nums.length;++i){
res[i]=map.get(old[i]);
}
return res;
}
19:Move Zeroes
Given an array nums
, write a function to move all 0
's to the end of it while maintaining the relative order of the non-zero elements.
For example, given nums = [0, 1, 0, 3, 12]
, after calling your function, nums
should be [1, 3, 12, 0, 0]
.
You must do this in-place without making a copy of the array.
此题:给出一个数组,要求把所有0元素移到后面,非0的保持原来的相对位置。要求只能在原数组用元素替换不能用新数组。
思路:此题如果按冒泡排序简化版来做的话,需要不断遍历找到0然后交换到末尾,时间复杂度为O(N^2)。注意到这里只要求非0的保持原来位置,后面的全是0。我们采取“用覆盖不用交换”的策略:由找0移动到后面转为找非0写入(覆盖)到前面index-1处。遍历一次数组后所有非0的都写入到0~index-1坐标下了,然后从index~nums.length-1全部赋值0即可。
public void moveZeroes(int[] nums) {
int index=0;
//找非0元素写到前面(用覆盖不用移动)
for(int i=0;i<nums.length;++i){
if(nums[i]!=0){
nums[index]=nums[i];
++index;
}
}
//后面的全是0
for(int i=index;i<nums.length;++i){
nums[i]=0;
}
}
20:Two Sum II - Input array is sorted
Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
此题:two sum题的升级版,经典的两指针迫近问题。
思路:用两个下标分别指向有序数组的两端,求数组最大值和最小值的和,然后与target比较,大了则右边坐标左移;小了则左边左边右移动;直到和等于target。由于题目说绝对有解,那么我们就可以一步步迫近最终解。
一开始,min+max>target,所以需要减小,而min已经是最小的,所以只能减小max,右下标左移。
...
直到,min+max<target,此时需要增大,由于上一次min+max>target,所以可知如果此时用max右移增大的话结果会大于target,所以只能用左下标右移来增大。
...
直到min+max=target,此时的左边就是所求了。
public int[] twoSum(int[] numbers, int target) {
if(numbers==null || numbers.length < 1) return null;
int[] res=null;
int min=0;
int max=numbers.length-1;
while(min<max){
if(numbers[min]+numbers[max]>target){
--max;
}else if(numbers[min]+numbers[max]<target){
++min;
}else{
return res=new int[]{min+1,max+1};
}
}
return res;
}