26.二叉搜索树与双向链表
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
中序遍历思路:
按照右中左的顺序,中序遍历对节点的访问顺序和转换完链表从左到右的顺序是一样的。所以在中序遍历时完成相邻两个节点的互指即可。
具体做法是把前一个节点记录下来然后pre->right=cur;cur->left=pre。
/** public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ public class Solution { TreeNode pre = null; public TreeNode Convert(TreeNode pRootOfTree) { if(pRootOfTree == null) return pRootOfTree; Convert(pRootOfTree.right); if(pre == null){ pre = pRootOfTree; } else { pre.left = pRootOfTree; pRootOfTree.right = pre; pre = pRootOfTree; } Convert(pRootOfTree.left); return pre; } }
最开始我采用的是这种解法,有两个问题:
1.采用左中右的中序遍历,遍历完之后头结点还得从右到左挪回来
2.更严重的问题是,我将pre设置为局部传递的变量,由于pre是引用的值传递,在递归回退的时候,pre的引用时上一次遍历pre的副本,而不是遍历后更改的值。解决方法就是讲pre设置为全局变量。
切记!!!java只有值传递!只有值传递!只有值传递!
对于基本类型,java都是传值。而对于引用类型,其实java也是通过值传递的,只是传递的值不是实例本身,而是实例的引用的副本。
参考java的传值与传引用
错误解法:
/** public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ public class Solution { public TreeNode Convert(TreeNode pRootOfTree) { if(pRootOfTree == null) return null; TreeNode pre = null; ConvertHelper(pRootOfTree,pre); TreeNode res = pRootOfTree; while(res.left != null){ res = res.left; } return res; } public void ConvertHelper(TreeNode cur, TreeNode pre){ if(cur == null) return; ConvertHelper(cur.left,pre); cur.left = pre; if(pre!=null) pre.right = cur; pre = cur; ConvertHelper(cur.right,pre); } }
非递归实现:
链接:https://www.nowcoder.com/questionTerminal/947f6eb80d944a84850b0538bf0ec3a5 来源:牛客网 import java.util.Stack; public class Solution { public TreeNode Convert(TreeNode pRootOfTree) { if(pRootOfTree == null) return pRootOfTree; TreeNode list = null; Stack<TreeNode> s = new Stack<>(); while(pRootOfTree != null || !s.isEmpty()){ if(pRootOfTree != null) { s.push(pRootOfTree); pRootOfTree = pRootOfTree.right; } else { pRootOfTree = s.pop(); if(list == null) list = pRootOfTree; else { list.left = pRootOfTree; pRootOfTree.right = list; list = pRootOfTree; } pRootOfTree = pRootOfTree.left; } } return list; } }
扫描二维码关注公众号,回复:
1531184 查看本文章
27.字符串的排列
题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
import java.util.ArrayList; import java.util.Collections; public class Solution { public ArrayList<String> Permutation(String str) { ArrayList<String> list = new ArrayList<String>(); if(str !=null && str.length() > 0){ PermutationHelper(str.toCharArray(),0,list); Collections.sort(list); } return list; } public void PermutationHelper(char[] cs, int i, ArrayList<String> list){ if(cs.length-1 == i){ String val = String.valueOf(cs); if(!list.contains(val)){ list.add(val); } }else{ for(int j=i; j<cs.length;j++){ swap(i,j,cs); PermutationHelper(cs,i+1,list); swap(i,j,cs); } } } public void swap(int i,int j,char[] cs){ char temp = cs[i]; cs[i] = cs[j]; cs[j] = temp; } }
最后一个循环是递归调用swap交换前后两个字符,在最后交换完成入List之后再交换回来,回到初始状态再进下一个循环
28.数组中出现次数超过一半的数字
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
第一种普通解法:耗时10ms
import java.util.*; public class Solution { public int MoreThanHalfNum_Solution(int [] array) { Map<Integer,Integer> count = new HashMap<>(); if(array.length == 1) return array[0]; for(int i:array){ if(!count.containsKey(i)){ count.put(i, 1); }else{ count.put(i,count.get(i)+1); if(count.get(i) > array.length/2) return i; } } return 0; } }
第二种解法:耗时10ms
采用阵地攻守的思想:
第一个数字作为第一个士兵,守阵地;count = 1;
遇到相同元素,count++;
遇到不相同元素,即为敌人,同归于尽,count--;当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,到最后还留在阵地上的士兵,有可能是主元素。
再加一次循环,记录这个士兵的个数看是否大于数组一般即可。
public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if(array.length == 1) return array[0]; int result = array[0]; int times = 0; for(int i = 0;i<array.length; i++){ if(times == 0){ result = array[i]; times = 1; }else if(result == array[i]){ times++; }else{ times--; } } times=0; for(int i=0;i<array.length;i++){ if(result==array[i]){ times++; } } if(times*2<=array.length){ result=0; } return result; } }
29.最小的K的个数
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
偷懒解法(利用jdk自带的排序api):
import java.util.*; public class Solution { public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { ArrayList<Integer> list = new ArrayList<>(); if(k>input.length) return list; Arrays.sort(input); for(int i:Arrays.copyOfRange(input, 0, k)){ list.add(i); } return list; } }