非递归层次遍历
import java.util.Queue;
import java.util.LinkedList;
public class Solution {
public int TreeDepth(TreeNode root) {
if(root == null)
return 0;
Queue<TreeNode> queue = new LinkedList();
int cur = 0, width = 0; //cur表明现在遍历到本层的第几个节点
int depth = 0;
queue.offer(root);
while(!queue.isEmpty())
{
width = queue.size(); //获取本层的宽度
cur = 0; //进入新一层,cur=0
while(cur < width)
{
TreeNode node = queue.poll();
if (node.left != null)
queue.offer(node.left);
if (node.right != null)
queue.offer(node.right);
cur++;
}
depth++;
}
return depth;
}
}
递归写法
public class Solution {
public int TreeDepth(TreeNode root) {
if(root == null)
return 0;
int left = TreeDepth(root.left);
int right = TreeDepth(root.right);
return Math.max(left,right) + 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(Math.abs(right - left) >=2)
return false;
return true;
}
public int TreeDepth(TreeNode root)
{
if(root == null)
return 0;
int left = TreeDepth(root.left);
int right = TreeDepth(root.right);
return Math.max(left,right) + 1;
}
}
一般的思路是使用HashMap,初次之外的方法是使用异或的技巧
异或技巧的思路要点:
- 用0逐个异或一个数组,数组中相同的数字会被抵消,最后i的结果相当于不重复的数组异或
- 对数组所有数异或后结果进行分析,判断出从后往前第一个为1的位置,以该位置对所有数进行分类,这样得到的两个数仅仅只包括一个不重复的数,随后分别对这两个数进行0异或
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if (array == null || array.length<2)
return;
int n = 0;
for (int i = 0;i < array.length; i++)
{
n ^=array[i];
}
int index = findBit1(n);
num1[0] = 0;
for(int i = 0;i <array.length;i++)
{
if(isBit1(array[i],index))
{
num1[0] ^= array[i];
}
else
num2[0] ^= array[i];
}
}
public int findBit1(int n)
{
int index = 0;
while ((n & 1) == 0 && index <= Integer.SIZE)
{
n >>= 1;
index++;
}
return index;
}
public boolean isBit1(int n, int index)
{
while (index != 0)
{
n >>= 1;
index--;
}
return ((n&1) == 1);
}
}
数组为递增排序
法1:HashMap
import java.util.ArrayList;
import java.util.HashMap;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> arrayList = new ArrayList<>();
if (array == null || array.length < 1)
return arrayList;
HashMap<Integer,Integer> map = new HashMap<>();
int[] temp = new int[2];
int min = Integer.MAX_VALUE;
for(int i:array)
{
if(!map.containsKey(sum - i))
map.put(i,sum-i);
else
{
if(i * (sum-1)<min)
{
arrayList.clear();
arrayList.add(sum - i);
arrayList.add(i);
}
}
}
return arrayList;
}
}
法2:双指针
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> list = new ArrayList<>();
if (array == null || array.length<1)
return list;
int l = 0;
int r = array.length - 1;
while (l <= r)
{
int temp = array[l] + array[r];
if (temp == sum)
{
list.add(array[l]);
list.add(array[r]);
break;
}
if (temp < sum)
l++;
if (temp > sum)
r--;
}
return list;
}
}
双指针的技巧
import java.util.ArrayList;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> allList = new ArrayList<>();
int l = 1;
int r = 2;
while (l < r)
{
int cur = getSum(l,r);
if (cur == sum)
{
ArrayList<Integer> list = new ArrayList<>();
for(int i = l; i <= r;i++)
list.add(i);
allList.add(list);
r++;
}
else if(cur > sum)
{
l++;
}
else if(cur < sum)
{
r++;
}
}
return allList;
}
public int getSum(int m, int n)
{
int sum = 0;
for (int i = m; i <= n;i++)
{
sum += i;
}
return sum;
}
}
先整体翻转,再翻转每一个单词,需要注意的是如果输入多个空格的情况,此时可以使用trim()的技巧
比较暴力的做法是从后往前一个一个处理
public class Solution {
public String ReverseSentence(String str) {
if (str.trim().equals("")) //检查是否是全有空格组成
return str;
String temp = reverse(str);
String [] strr = temp.split(" ");
for(int i = 0;i < strr.length;i++)
{
strr[i] = reverse(strr[i]);
}
StringBuilder sb = new StringBuilder();
for(int i = 0;i < strr.length;i++)
{
sb.append(strr[i] + " ");
}
return sb.toString().trim(); //trim()去掉多余的空格
}
public String reverse(String str)
{
StringBuilder sb = new StringBuilder(str);
return sb.reverse().toString();
}
}
先翻转要左移的字符串,再翻转整体字符串
public class Solution {
public String LeftRotateString(String str,int n) {
if (str.trim() == "")
return str;
if (n > str.length())
return "";
StringBuilder sb = new StringBuilder(str);
StringBuilder sb1 = new StringBuilder(sb.substring(0,n));
StringBuilder sb2 = new StringBuilder(sb.substring(n));
sb.replace(0,n,sb1.reverse().toString());
sb.replace(n,sb.length(),sb2.reverse().toString());
return sb.reverse().toString();
}
}
暴力做法
public class Solution {
public String LeftRotateString(String str,int n) {
if (str == null || str.length() < 1)
return "";
StringBuilder temp = new StringBuilder();
for (int i = 0; i < n; i++)
{
temp.append(str.charAt(i));
}
StringBuilder sb = new StringBuilder(str);
sb.delete(0,n);
for (int i = 0; i < temp.length(); i++)
{
sb.append(temp.charAt(i));
}
return sb.toString();
}
}
先定义快慢两个指针,找到两个指针的相遇点,随后将一指针指向头结点,两个指针同时向后移动,再次相遇的结点为环入口
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if (pHead == null || pHead.next == null || pHead.next.next == null)
return null;
ListNode p1 = pHead.next;
ListNode p2 = pHead.next.next;
int count = 1;
while (p1 != p2) {
if (p2.next != null && p2.next.next!= null)
{
p1 = p1.next;
p2 = p2.next.next;
}
else
return null;
}
p1 = pHead;
while (p1 != p2)
{
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
}
有对子也要返回false,0可以当作任何牌
import java.util.Arrays;
public class Solution {
public boolean isContinuous(int [] numbers) {
if (numbers == null || numbers.length != 5 )
return false;
Arrays.sort(numbers);
int zeroSum = 0;
int blank = 0;
for (int i = 0; i < numbers.length - 1; i++)
{
if (numbers[i] == 0)
{
zeroSum++;
continue;
}
if (numbers[i + 1] == numbers[i])
return false;
blank += numbers[i + 1] - numbers[i] - 1;
}
if (blank <= zeroSum)
return true;
return false;
}
}
暴力解法,链表模拟
import java.util.LinkedList;
public class Solution {
public int LastRemaining_Solution(int n, int m) {
LinkedList<Integer> list = new LinkedList<>();
for (int i = 0;i < n;i++)
{
list.add(i);
}
int index = 0;
while (list.size() > 1)
{
index = (index + m - 1)%list.size();
list.remove(index);
}
return list.size() == 1 ? list.get(0):-1;
}
}
递推
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if(n < 1 || m < 1)
return -1;
if(n == 1)
return 0;
return (LastRemaining_Solution(n-1, m)+m)%n;
}
}
不能使用条件语句
public class Solution {
public static int Sum_Solution(int n) {
int sum = n;
boolean flag = (sum > 0) && ((sum += Sum_Solution(--n))> 0);
return sum;
}
}
public class Solution {
public int Add(int num1,int num2) {
do {
int sum = num1 ^ num2; //异或一次
int temp = (num1 & num2)<<1;//确定进位
num1 = sum;
num2 = temp;
}
while (num2 != 0);
return num1;
}
}
public class Solution {
public static int StrToInt(String str) {
if (str == null)
return 0;
str = str.trim();
if (str.length() == 0)
return 0;
int flag = 1;
int index = 0;
if (str.charAt(0) == '+')
index++;
if (str.charAt(0) == '-')
{
flag = -1;
index++;
}
int sum = 0;
for (int i = index; i < str.length(); i++)
{
if (str.charAt(i) < '0' || str.charAt(i) > '9')
return 0;
int n = flag > 0?((int)(str.charAt(i) - '0')):((int)('0' - str.charAt(i)));
sum = sum * 10 + n;
//判断是否出借,如果出界了,符号会发生反转
if (sum >= 0 && flag < 0 || sum < 0 && flag > 0)
return 0;
}
return sum;
}
}
利用数组本身的特性
public class Solution {
public boolean duplicate(int numbers[],int length,int [] duplication) {
if (numbers == null || numbers.length == 0)
return false;
for (int i:numbers)
{
if (i < 0 || i >=length)
return false;
}
for (int j = 0; j < numbers.length; j++)
{
while (j != numbers[j])
{
if (numbers[j] == numbers[numbers[j]])
{
duplication[0] = numbers[j];
return true;
}
int temp = numbers[j];
numbers[j] = numbers[temp];
numbers[temp] = temp;
}
}
return false;
}
}
Hash法
public class Solution {
public boolean duplicate(int numbers[],int length,int [] duplication) {
if (numbers == null || numbers.length == 0)
return false;
for (int i:numbers)
{
if (i < 0 || i >=length)
return false;
}
boolean[] bool = new boolean[length];
for (int i = 0; i < length; i++)
{
if (bool[numbers[i]] == true)
{
duplication[0] = numbers[i];
return true;
}
else
bool[numbers[i]] = true;
}
return false;
}
}
非递归写法
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
ArrayList<ArrayList<Integer>> allList = new ArrayList<>();
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
if (pRoot == null)
return allList;
Queue<TreeNode> queue = new LinkedList<>();
int width = 0;
int cur = 0;
queue.offer(pRoot);
while (!queue.isEmpty())
{
width = queue.size();
cur = 0;
ArrayList<Integer> list = new ArrayList<>();
while (cur < width)
{
TreeNode node = queue.poll();
list.add(node.val);
if (node.left != null)
queue.offer(node.left);
if (node.right !=null)
queue.offer(node.right);
cur++;
}
allList.add(list);
}
return allList;
}
}
递归写法
import java.util.ArrayList;
public class Solution {
ArrayList<ArrayList<Integer>> allList = new ArrayList<>();
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
if (pRoot == null)
return allList;
dfs(pRoot,1,allList);
return allList;
}
void dfs(TreeNode root, int depth, ArrayList<ArrayList<Integer>> list)
{
if (depth > list.size())
list.add(new ArrayList<>());
list.get(depth-1).add(root.val);
if (root.left != null)
dfs(root.left,depth+1,list);
if (root.right != null)
dfs(root.right,depth+1,list);
}
}
public class Solution {
//Insert one char from stringstream
String s = "";
char[] hash = new char[128];
public void Insert(char ch)
{
s += ch;
hash[ch]++;
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
for (int i = 0; i<s.length();i++)
{
if (hash[s.charAt(i)] == 1)
return s.charAt(i);
}
return '#';
}
}
法1:借用栈。通过左右子树进入栈的顺序不同构建从左到右和从右到左
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
ArrayList<ArrayList<Integer>> allList = new ArrayList<>();
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
if (pRoot == null)
return allList;
int layer = 1;
Stack<TreeNode> stack1 = new Stack<>(); //存储奇数层
Stack<TreeNode> stack2 = new Stack<>(); //存储偶数层
stack1.push(pRoot);
while (!stack1.isEmpty() || !stack2.isEmpty()) {
ArrayList<Integer> list = new ArrayList<>();
if (layer % 2 != 0) {
while (!stack1.isEmpty()) {
TreeNode node = stack1.pop();
if (node != null) {
list.add(node.val);
if (node.left != null) stack2.push(node.left);
if (node.right != null) stack2.push(node.right);
}
}
layer++;
allList.add(list);
}
else if (layer % 2 == 0) {
while (!stack2.isEmpty()) {
TreeNode node2 = stack2.pop();
if (node2 != null) {
list.add(node2.val);
if (node2.right != null) stack1.push(node2.right);
if (node2.left != null) stack1.push(node2.left);
}
}
layer++;
allList.add(list);
}
}
return allList;
}
}
法2:层次遍历,遇到偶数则反转列表
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
ArrayList<ArrayList<Integer>> allList = new ArrayList<>();
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
if (pRoot == null)
return allList;
int layer = 1;
int cur;
int width;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(pRoot);
while (!queue.isEmpty()) {
width = queue.size();
cur = 0;
ArrayList<Integer> list = new ArrayList<>();
while (cur < width) {
TreeNode node = queue.poll();
list.add(node.val);
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
cur++;
}
if (layer %2 != 0)
{
layer++;
allList.add(list);
}
else if (layer %2 == 0)
{
layer++;
allList.add(reverseList(list));
}
}
return allList;
}
public ArrayList<Integer> reverseList(ArrayList<Integer> list)
{
ArrayList<Integer> newList = new ArrayList<>();
for (int i = list.size() - 1; i >= 0; i--)
{
newList.add(list.get(i));
}
return newList;
}
}
public class Solution {
public static int getMaxDiff(int[] nums)
{
if (nums == null || nums.length<2)
return 0;
int min = nums[0];
int maxDiff = nums[1] - min;
for (int i = 2; i < nums.length; i++)
{
if (nums[i -1] < min)
min = nums[i -1];
int curDiff = nums[i] - min;
if (curDiff > maxDiff)
maxDiff = curDiff;
}
return maxDiff;
}
public static void main(String[] args) {
int[] nums = {9,11,8,5,7,12,16,14};
System.out.println(getMaxDiff(nums));
}
}
法1,大小堆
如果输入是奇数,中位数为前一部分的最大值
如果输入是偶数,中位数为大顶堆和小顶堆值之和的一半
两个堆应该始终满足:
大顶堆的堆顶元素,小于或者等于小顶堆的堆顶元素
大顶堆的元素个数过载与小顶堆的元素个数相等,或者多1
当两个堆元素和为偶数,为了让大顶堆中多一个元素,大顶堆->小顶堆->大顶堆
当元素和为奇数,此时小顶堆必须多一个元素,这样大顶堆和小顶堆的元素个数才能相等,大顶堆->小顶堆
import java.util.PriorityQueue;
public class Solution {
PriorityQueue<Integer> minQueue = new PriorityQueue<>();
PriorityQueue<Integer> maxQueue = new PriorityQueue<>((x,y)->(y-x));
int count = 0;
public void Insert(Integer num) {
count++;
maxQueue.offer(num);
minQueue.offer(maxQueue.poll());
if (count % 2 != 0)
maxQueue.offer(minQueue.poll());
}
public Double GetMedian() {
if (count % 2 == 0)
return (double)(maxQueue.peek() + minQueue.peek())/2;
else
return (double)maxQueue.peek();
}
}
直接递归
public class Solution {
int count = 0;
public TreeNode KthNode(TreeNode pRoot, int k)
{
if (pRoot!=null)
{
TreeNode LNode = KthNode(pRoot.left,k);
if (LNode != null)
return LNode;
count++;
if (count == k)
return pRoot;
TreeNode RNode = KthNode(pRoot.right,k);
if (RNode != null)
return RNode;
}
return null;
}
}
借助列表
import java.util.ArrayList;
public class Solution {
ArrayList<TreeNode> list = new ArrayList<>();
public TreeNode KthNode(TreeNode pRoot, int k)
{
if (pRoot == null || k <=0)
return null;
dfs(pRoot);
if (k > list.size())
return null;
return list.get(k-1);
}
public void dfs(TreeNode root)
{
if (root.left != null)
dfs(root.left);
list.add(root);
if (root.right != null)
dfs(root.right);
}
}
双端队列
import java.util.ArrayDeque;
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> list = new ArrayList<>();
if (num == null || num.length <=0 || size == 0 || size > num.length)
return list;
ArrayDeque<Integer> deque = new ArrayDeque<>();
for (int i = 0; i < size; i++)
{
while (!deque.isEmpty() && num[i] > num[deque.peekLast()])
deque.removeLast();
deque.addLast(i);
}
for (int i = size; i < num.length; i++)
{
list.add(num[deque.peekFirst()]);
while (!deque.isEmpty() && num[i] >= num[deque.peekLast()])
deque.removeLast();
if (!deque.isEmpty() && (i - deque.peekFirst()) >= size)
deque.removeFirst();
deque.addLast(i);
}
list.add(num[deque.peekFirst()]);
return list;
}
}
暴力解法
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer
> maxInWindows(int [] num, int size)
{
ArrayList<Integer> list = new ArrayList<>();
if (num == null || size == 0 || num.length <= 0 || num.length < size)
return list;
int []max = new int[2];
int i = 0;
int j = size - 1;
while (j <= num.length - 1)
{
max = findMax(num,i,j);
list.add(max[1]);
i++;j++;
}
return list;
}
public int[] findMax(int[] num, int l, int r)
{
int max = num[l];
int maxIndex = l;
for (int i = l; i <= r; i++)
{
if (num[i] > max)
{
max = num[i];
maxIndex = i;
}
}
return new int[]{maxIndex,max};
}
}