先声明一下,从第三篇到第四篇中间间隔了很久,现在是读研期间刷题了,语言也决定切为java. 还是从简单题开始,一点点来。
94.二叉树的中序遍历
递归遍历:
- 前序遍历:打印 - 左 - 右
- 中序遍历:左 - 打印 - 右
- 后序遍历:左 - 右 - 打印
递归和迭代的方法其实都不难,但是有一个新方法是没见过的。
Morris 遍历算法是另一种遍历二叉树的方法,它能将非递归的中序遍历空间复杂度降为O(1).
大致就是想把二叉树按一定顺序捋成链表的样子。
代码:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
TreeNode predecessor = null;
while(root != null){
if(root.left == null){
res.add(root.val);
root = root.right;
}
else{
predecessor = root.left;
// predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
while(predecessor.right != null && predecessor.right != root){
predecessor = predecessor.right;
}
if(predecessor.right != null){
res.add(root.val);
root = root.right;
}
else{
predecessor.right = root;
root = root.left;
}
}
}
return res;
}
}
169.多数元素
- 方法一:哈希表映射
其实是比较简单的暴力搜索思路,不过用哈希表来加速查找,避免超时。
这里也学了一下哈希表的用法。
class Solution {
private Map<Integer, Integer> countNums(int[] nums){
Map<Integer, Integer> counts = new HashMap<Integer, Integer>();
for( int num:nums){
if(!counts.containsKey(num)){
counts.put(num,1);
}
else{
counts.put(num,counts.get(num)+1);
}
}
return counts;
}
public int majorityElement(int[] nums) {
int length = nums.length;
Map<Integer, Integer> counts = countNums(nums);
for(Map.Entry<Integer, Integer> countsEntry:counts.entrySet()){
if(countsEntry.getValue() > length/2){
return countsEntry.getKey();
}
}
return nums[length-1];
}
}
- 排序
这里有个重点就是多数元素超过了列表的一半,所以排序后中间那个数一定是我们要找的多数元素。
老规矩,用移位代替乘法。
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length >> 1];
}
}
- 摩尔投票法
这个让我想起摊还分析。
如果遇到相同的就加一票,不同的减一票,如果票数为0 ,就换候选人。由于多数元素超过了列表的一半,所以在票数为负之前一定能再次遇到一个。
class Solution {
public int majorityElement(int[] nums) {
int candidate = nums[0];
int votes = 1;
for(int i = 1; i < nums.length ; i++){
if(candidate == nums[i]){
votes += 1;
}
else{
votes -= 1;
if(votes == 0){
candidate = nums[i];
votes = 1;
}
}
}
return candidate;
}
}
168.Excel表列名称
这是一个进制转换问题,但涉及到字符串而不单纯是数字,用到了一个东西叫stringBuilder,这里的char类型强制转换也比C的快乐多了哈哈。
需要小心的是,由于是1对应A,而不是0对应A,在计算之前需要将当前值–,再取余。
class Solution {
public String convertToTitle(int columnNumber) {
StringBuilder columnname = new StringBuilder();
while(columnNumber > 0){
columnNumber--;
columnname.append((char)(columnNumber%26 + 'A'));
columnNumber = columnNumber/26;
}
columnname.reverse();
return columnname.toString();
}
}
171.Excel表列名称
与168就是相反的计算。这里字符串的处理有点像python,但要调用相对应的方法。
这里求长度是方法.length(),而前面数组求长度是成员变量.length
具体为啥,查了一下,显然也有人思考过这个问题 为什么Java获取数组的长度用.length
class Solution {
public int titleToNumber(String columnTitle) {
int columnNumber = 0;
for(int i=columnTitle.length()-1 ; i>-1 ; i--){
int cur = (int)(columnTitle.charAt(i) - 'A') + 1;
columnNumber += cur*(Math.pow(26,columnTitle.length()-i-1));
}
return columnNumber;
}
}