算法
寻找逆序对(归并思想)
public int InversePairs(int [] array) {
if(array == null || array.length == 0) return 0;
int i = 0;
int j = array.length - 1;
int[] copy = new int[array.length];
return countPairs(array,copy,i,j);
}
public int countPairs(int[] array,int[] copy,int left,int right){
if(left >= right) return 0;
int res = 0;
int mid = left + (right - left) / 2;
int leftNum = countPairs(array,copy,left,mid) % 1000000007;
int rightNum = countPairs(array,copy,mid + 1,right) % 1000000007;
int i = left;
int j = mid;
int m = mid + 1;
int n = right;
int k = right;
while(j >= i && n >= m){
if(array[j] > array[n]){
res += (n - mid); // core code
if(res > 1000000007) res %= 1000000007;
copy[k--] = array[j--];
}
else copy[k--] = array[n--];
}
while(j >= i){
copy[k--] = array[j--];
}
while(n >= m){
copy[k--] = array[n--];
}
for(int p = left; p <= right; p++){
array[p] = copy[p];
}
return (res + leftNum + rightNum) % 1000000007;
}
寻找波峰(只有一个波峰)----二分思想
public int findPeakElement(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int i = 0;
int j = nums.length -1;
while(i <= j){
int m = i + (j - i) / 2;
//注意此处的越界
int target = (m + 1 == nums.length) ? Integer.MIN_VALUE : nums[m + 1];
if(nums[m] < target) i = m + 1;
else j = m - 1;
}
return i;
}
循环数组求最小值(无重复)----二分思想
public int findMin(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int right = nums.length - 1;
int i = 0;
int j = nums.length - 1;
while(i <= j){
int m = i + (j - i) / 2;
if(nums[m] > nums[right]) i = m + 1; //core code
else j = m - 1;
}
return nums[i];
}
循环数组求最小值(有重复)----二分思想
public int findMin(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int i = 0;
int j = nums.length - 1;
while(nums[i] >= nums[j]){
if(j - i == 1){
return nums[j];
}
else{
int m = i + (j - i) / 2;
if(nums[i] == nums[m] && nums[j] == nums[m]){
return getMin(nums,i,j);
}
//core code
else if(nums[m] > nums[j]) i = m + 1;
else j = m;
}
}
return nums[i];
}
public int getMin(int[] nums,int i,int j){
int res = Integer.MAX_VALUE;
while(i <= j){
res = Math.min(res,nums[i]);
i++;
}
return res;
}
循环数组查找(无重复)----二分思想
public int search(int[] nums, int target) {
if(nums == null || nums.length == 0) return -1;
int i = 0;
int j = nums.length - 1;
while(i <= j){
int m = i + (j - i) / 2;
if(nums[m] == target) return m;
if(nums[m] >= nums[i]){
if(target >= nums[i] && target < nums[m]) j = m - 1;
else i = m + 1;
}
else{
if(target > nums[m] && target <= nums[j]) i = m + 1;
else j = m - 1;
}
}
return -1;
}
循环数组查找(有重复)----二分思想
public boolean search(int[] nums, int target) {
if(nums == null || nums.length == 0) return false;
int i = 0;
int j = nums.length - 1;
while(i <= j){
int m = i + (j - i) / 2;
if(nums[m] == target) return true;
if(nums[m] > nums[i]){
if(target >= nums[i] && target < nums[m]) j = m - 1;
else i = m + 1;
}
else if(nums[m] < nums[i]){
if(target > nums[m] && target < nums[j]) i = m + 1;
else j = m - 1;
}
else{
i = i + 1;
}
}
return false;
}
计算subtree的val和----后序迭代思想(Most Frequent Subtree Sum)
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
int maxCount = 0;
public int[] findFrequentTreeSum(TreeNode root) {
if(root == null) return new int[0];
List<Integer> res = new ArrayList<Integer>();
postOrder(root,map);
for(Integer i : map.keySet()){
if(map.get(i) == maxCount) res.add(i);
}
int[] ans = new int[res.size()];
for(int i = 0; i < res.size(); i++){
ans[i] = res.get(i);
}
return ans;
}
public int postOrder(TreeNode root,HashMap<Integer,Integer> map){
if(root == null) return 0;
int left = postOrder(root.left,map);
int right = postOrder(root.right,map);
int sum = root.val + left + right;
int count = map.getOrDefault(sum,0) + 1;
map.put(sum,count);
maxCount = Math.max(maxCount,count);
return sum;
}
树的遍历(非递归)
后序
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if(root == null) return res;
Stack<TreeNode> s = new Stack<>();
s.push(root);
TreeNode pre = null;
while(!s.isEmpty()){
TreeNode node = s.peek();
if((node.left == null && node.right == null) || (pre != null && (node.left == pre || node.right == pre))){
res.add(node.val);
pre = node;
s.pop();
}
else{
if(node.right != null) s.push(node.right);
if(node.left != null) s.push(node.left);
}
}
return res;
}
前序
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Stack<TreeNode> s = new Stack<>();
if(root == null) return res;
while(!s.isEmpty() || root != null){
s.push(root);
res.add(root.val);
root = root.left;
while(!s.isEmpty() && root == null){
root = s.pop().right;
}
}
return res;
}
中序
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Stack<TreeNode> s = new Stack<>();
if(root == null) return res;
while(!s.isEmpty() || root != null){
s.push(root);
root = root.left;
while(!s.isEmpty() && root == null){
root = s.pop();
res.add(root.val);
root = root.right;
}
}
return res;
}
最大路径和----后序迭代思想(Binary Tree Maximum Path Sum)
public int maxValue;
public int maxPathSum(TreeNode root) {
maxValue = Integer.MIN_VALUE;
maxPathDown(root);
return maxValue;
}
public int maxPathDown(TreeNode root){
if(root == null) return 0;
int left = Math.max(0,maxPathDown(root.left));
int right = Math.max(0,maxPathDown(root.right));
maxValue = Math.max(maxValue,left + right + root.val);
return Math.max(left,right) + root.val;
}
BST转双向链表
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree == null) return null;
TreeNode pre = null;
TreeNode root = null;
boolean f = true;
Stack<TreeNode> s = new Stack<>();
while(!s.isEmpty() || pRootOfTree != null){
s.push(pRootOfTree);
pRootOfTree = pRootOfTree.left;
while(!s.isEmpty() && pRootOfTree == null){
pRootOfTree = s.pop();
if(f){
pre = pRootOfTree;
root = pRootOfTree;
f = false;
}
else{
pRootOfTree.left = pre;
pre.right = pRootOfTree;
pre = pRootOfTree;
}
pRootOfTree = pRootOfTree.right;
}
}
return root;
}
最长无重复字符串----双指针(Longest Substring Without Repeating Characters)
public int lengthOfLongestSubstring(String s) {
if(s == null || s.isEmpty()) return 0;
HashMap<Character,Integer> map = new HashMap<Character,Integer>();
//i表示字符串终点,j表示下次查找的起点,只会越来越大
int j = 0;
int max = 0;
for(int i = 0; i < s.length(); i++){
if(map.containsKey(s.charAt(i))){
j = Math.max(j,map.get(s.charAt(i)) + 1);
}
map.put(s.charAt(i),i);
max = Math.max(max,i - j + 1);
}
return max;
}
最长公共子序列----dp
public static String LCS(String str,String ptr){
StringBuffer s = new StringBuffer();
int[][] dp = new int[str.length() + 1][ptr.length() + 1];
for(int i = 1; i < dp.length; i++){
for(int j = 1; j < dp[0].length; j++){
if(str.charAt(i - 1) == ptr.charAt(j - 1)){
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else{
dp[i][j] = Math.max(dp[i - 1][j],dp[i][ j - 1]);
}
}
}
int i = str.length();
int j = ptr.length();
while(i > 0 && j > 0){
if(str.charAt(i - 1) == ptr.charAt(j - 1)){
s = s.append(str.charAt(i - 1));
i--;
j--;
}
else{
if(dp[i][j - 1] > dp[i - 1][j]) j--;
else i--;
}
}
return s.reverse().toString();
}
最长公共子串----dp
public static String LCS(String str,String ptr){
StringBuffer s = new StringBuffer();
int maxLen = Integer.MIN_VALUE;
int row = 0;
int col = 0;
int[][] dp = new int[str.length()][ptr.length()];
for(int i = 0; i < dp.length; i++){
for(int j = 0; j < dp[0].length; j++){
if(str.charAt(i) == ptr.charAt(j)){
if(i == 0 || j == 0) dp[i][j] = 1;
else dp[i][j] = dp[i - 1][j - 1] + 1;
if(dp[i][j] > maxLen){
maxLen = dp[i][j];
row = i;
col = j;
}
}
}
}
while(row >= 0 && col >= 0 && maxLen > 0){
s = s.append(str.charAt(row));
row--;
col--;
maxLen--;
}
return s.reverse().toString();
}