美团面试的时候,写随机快排,quicksort函数的quicksort(array,left,index - 1)写错成quicksort(array,left,index)导致stackoverflowerror
解法1:快排
import java.util.*;
class Solution {
public int[] smallestK(int[] arr, int k) {
int[] answer = new int[k];
quicksort(arr,0,arr.length - 1);
for(int i = 0;i < k;i ++) {
answer[i] = arr[i];
}
return answer;
}
public void quicksort(int[] array,int left,int right) {
if(left < right) {
int index = partition(array,left,right);
//quicksort(array,left,index);
quicksort(array,left,index - 1);
quicksort(array,index + 1,right);
}
}
public int partition(int[] array,int left,int right) {
Random random = new Random();
int flag = random.nextInt(right - left + 1) + left;
int pivot = array[flag];
//swap(array,flag,array.length - 1);
swap(array,flag,right);
//int pivot = array[flag];
int index = left - 1;
for(int i = left;i <= right;i ++) {
if(array[i] <= pivot) {
index ++;
swap(array,index,i);
}
}
return index;
}
//java函数交换数组的两个数字可以,单独交换两个数字不可以,类似传参与传引用
public void swap(int[] array,int i,int j) {
int tem = array[i];
array[i] = array[j];
array[j] = tem;
}
}
解法2:实现堆排序
待实现
解法:
注意:
1.new 一个比较器的时候,new Comparator<> (T) {重写的compare方法},T是代表一个类型,其实就是泛型,不能是int,long,float,得是Integer,Float,Long等对应的包装类型。但是int[],long[],float[]可以。
Arrays.sort(nums1,new Comparator
public int compare(Integer a,Integer b) {
return a * 10 + b - b * 10 + a;
}
});
2.对于本题,比较器是比较两个数,比如30和3,是303大还是330大,因此使用Integer数组不方便,两个数的位数不一样,因此使用String的数组,“30” + “3”可以直接拼接,拼接之后(“30” + “3”).compareTo("3" + "30");用String.valueOf()这个静态方法(重载的,建议)可以得到数字对应的String。
3.另外,可以有String类型的数组不可以有Stringbuilder和StringBuffer类型的数组,虽然创建StringBuilderStringBuffer的数组不报错,但是数组的内容就不能改变了,个人认为如果改变,不符合数组的内存地址连续性。
4.Comparator与Comparable:
https://blog.csdn.net/weixin_34066347/article/details/85621968
https://blog.csdn.net/qq_40693828/article/details/81409004?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3.channel_param
class Solution {
public String minNumber(int[] nums) {
//
/*
Integer[] nums1 = new Integer[nums.length];
for(int i = 0; i < nums.length;i ++) {
nums1[i] = new Integer(nums[i]);
}
StringBuilder sb = new StringBuilder();
Arrays.sort(nums1,new Comparator() {
public int compare(Integer a,Integer b) {
return a * 10 + b - b * 10 + a;
}
});
*/
String[] nums1 = new String[nums.length];
for(int i = 0; i < nums.length;i ++) {
nums1[i] = String.valueOf(nums[i]);
}
StringBuilder sb = new StringBuilder();
Arrays.sort(nums1,new Comparator() {
public int compare(String a,String b) {
//return Integer.parseInt(a + b) - Integer.parseInt(b + a);
return (a + b).compareTo((b + a));
}
});
for(int i = 0;i < nums1.length;i ++) {
sb.append(nums1[i]);
}
return sb.toString();
}
}
解法:PriorityQueue是用堆实现的
待完成:用数组实现堆
class Solution {
public int findKthLargest(int[] nums, int k) {
if(k > nums.length){
return 0;
}
/*
PriorityQueue minHeap = new PriorityQueue<>(nums.length,(a,b) -> a - b);
for(int i = 0;i < nums.length;i ++){
minHeap.add(nums[i]);
}
for(int i = 0;i < nums.length - k;i ++){
minHeap.poll();
}
return minHeap.peek();
*/
PriorityQueue minHeap = new PriorityQueue<>(k,(a,b) -> a - b);
for(int i = 0;i < k;i ++){
minHeap.add(nums[i]);
}
for(int i = k;i < nums.length;i ++){
if(nums[i] > minHeap.peek()){
minHeap.poll();
minHeap.add(nums[i]);
}
}
return minHeap.peek();
}
}
解法:这是滑动窗口系列题目之一
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.length() <= 1){
return s.length();
}
HashMap map = new HashMap<>();
int left = 0;
int max = 0;
for(int i = 0;i < s.length();i ++){
if(map.containsKey(s.charAt(i))){
//更新left的时候与i无关
left = Math.max(map.get(s.charAt(i)) + 1,left);
}
//更新max
max = Math.max(max,i - left + 1);
//添加map
map.put(s.charAt(i),i);
}
return max;
}
}
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode ans = reserveN(head,2);
ans.next.next = swapPairs(ans.next.next);
return ans;
}
ListNode lastofnext = null;
//从head节点开始反转N个链表
public ListNode reserveN(ListNode head,int N){
if(N == 1){
lastofnext = head.next;
return head;
}
//last是指向反转后头节点的指针,因此应返回last
ListNode last = reserveN(head.next,N - 1);
head.next.next = head;
head.next = lastofnext;
//返回的是last而不是head
return last;
}
}
解法:使用HashSet,符合题意的最长递增子序列的开始数字X,set里肯定不包含X - 1
比如最长的递增子序列是 2 3 4,那么1肯定不能在数组和set里。
class Solution {
public int longestConsecutive(int[] nums) {
if(nums.length <= 1) {
return nums.length;
}else {
HashSet set = new HashSet<>();
int answer = 1;
int currentlength;
int currentnumber;
for(int i = 0;i < nums.length;i ++) {
set.add(nums[i]);
}
for(int i = 0;i < nums.length;i ++) {
//点睛之处,对于数N,如果N - 1也在set里,那么最长的递增序列一定不是从N开始的,
//最长的递增序列,开始的数字X,set里肯定没有X - 1
if(! set.contains(nums[i] - 1)) {
currentlength = 1;
currentnumber = nums[i];
while(set.contains(currentnumber + 1)) {
currentlength ++;
currentnumber ++;
}
answer = Math.max(answer,currentlength);
}
}
return answer;
}
}
}
解法:一般会问递归的解法。
class Solution {
StringBuilder sb;
public String reverseWords(String s) {
sb = new StringBuilder();
//第一个单词变成最后一个单词,因此第一个单词加入sb的时候,不加空格
getReverseWord(sb,s,0,false);
return sb.toString();
}
//把单词存储到sb中,left表示从s的下标left开始添加下一个单词,flag表示在sb后面添加单词之后,sb后面还要不要加空格,原来的第一个单词加入sb之后,sb后面不需要加了
public void getReverseWord(StringBuilder sb,String s,int left,boolean flag) {
while(left < s.length() && s.charAt(left) == ' ') {
left ++;
}
//left指向下一个单词的开始字母,或者left等于s.length()
if(left == s.length()) {
return;
}
int right = left;
//right指向空格(left指向那个单词之后的第一个空格)或者right等于s.Length()
while(right < s.length() && s.charAt(right) != ' ') {
right ++;
}
getReverseWord(sb,s,right,true);
//下面可以代替上面的for循环,
//sb.append(s.substring(left,right));
//为什么是小于right?因为right没有指向单词的字母
for(int i = left;i < right;i ++) {
sb.append(s.charAt(i));
}
if(flag) {
sb.append(' ');
}
}
}
解法:迭代,很明显n个外观数需要依靠第n-1个外观数得到
class Solution {
public String countAndSay(int n) {
if(n == 1){
return "1";
}else{
String before = countAndSay(n - 1);
StringBuilder sb = new StringBuilder();
int index = 0;
while(index < before.length()){
int counter = 1;
char character = before.charAt(index);
while(index + 1 < before.length() && before.charAt(index + 1) == character){
index ++;
counter ++;
}
sb.append(counter);
sb.append(character);
index ++;
}
return sb.toString();
}
}
}
class Solution {
//
public ArrayList[] graph;
//点如果涂颜色,就加入map
public HashMap map;
//0代表红色,1代表蓝色
public boolean possibleBipartition(int N, int[][] dislikes) {
graph = new ArrayList[N + 1];
map = new HashMap();
for(int i = 0;i <= N;i ++){
graph[i] = new ArrayList();
}
//graph[i]表示i + 1不能共存的链表
for(int i = 0;i < dislikes.length;i ++){
graph[dislikes[i][0]].add(dislikes[i][1]);
graph[dislikes[i][1]].add(dislikes[i][0]);
}
for(int i = 1;i <= N;i ++){
if(! map.containsKey(i) && ! dfs(i,0)){
return false;
}
}
return true;
}
//把node的节点涂成color,是否合理
public boolean dfs(int node,int color){
//如果node已经存在,判断node的值与color是否相同
if(map.containsKey(node)){
return map.get(node) == color;
}
//如果不含有key
map.put(node,color);
for(int i = 0;i < graph[node].size();i ++){
//^是逐位
if(! dfs(graph[node].get(i),color ^ 1)){
return false;
}
}
return true;
}
}
解法:待实现:贪心+二分查找+动态规划,也就是先尽量换大的零钱
class Solution {
public int coinChange(int[] coins, int amount) {
if(amount == 0){
return 0;
}
//dp[i]代表凑成i元,需要的硬币个数
int[] dp = new int[amount + 1];
Arrays.sort(coins);
for(int i = 0;i < coins.length && coins[i] <= amount;i ++){
dp[coins[i]] = 1;
}
if(dp[amount] != 0){
return dp[amount];
}
for(int i = coins[0];i <= amount;i ++){
if(dp[i] == 1){
continue;
}else{
//下面的超时间
/*
int min = Integer.MAX_VALUE;
for(int j = coins[0];j <= i - coins[0];j ++){
if(dp[j] != 0 && dp[i - j] != 0){
min = Math.min(min,dp[j] + dp[i - j]);
}
}
if(min == Integer.MAX_VALUE){
dp[i] = 0;
}else{
dp[i] = min;
}
*/
int min = Integer.MAX_VALUE;
for(int j = 0;j < coins.length && coins[j] <= i;j ++){
if(dp[i - coins[j]] != 0){
min = Math.min(dp[coins[j]] + dp[i - coins[j]],min);
}
}
dp[i] = min == Integer.MAX_VALUE ? 0 : min;
}
}
//System.out.println(dp[10]);
return dp[amount] == 0 ? -1 : dp[amount];
}
public int find(int[] array,int target){
return 1;
}
}
class Solution {
public int coinChange(int[] coins,int amount) {
if(amount == 0){
return 0;
}
int[] dp =new int[amount + 1];
//第一个不一样的地方
Arrays.fill(dp,amount + 1);
//循环计算dp[i]
//第二个不一样的地方
dp[0] = 0;
//金钱的循环再外面,否则会出现重复的情况
for(int coin : coins){
for(int i = coin;i <= amount;i ++){
//第三个不一样的地方
dp[i] = Math.min(dp[i],dp[i - coin] + 1);
}
}
//第四个不一样的地方
return dp[amount] == amount + 1 ? -1 : dp[amount];
}
}
解法:类似与爬楼梯问题
class Solution {
//类似于爬楼梯
public int change(int amount, int[] coins) {
if(amount == 0){
return 1;
}
int[] dp =new int[amount + 1];
//循环计算dp[i]
dp[0] = 1;
//金钱的循环再外面,否则会出现重复的情况
for(int coin : coins){
for(int i = coin;i <= amount;i ++){
//相当于爬楼梯问题
//dp[n] = dp[n - 1] + dp[n - 2]
dp[i] += dp[i - coin];
}
}
return dp[amount];
}
}
解法:递减栈
class Solution {
//递减栈的思想
public int[] dailyTemperatures(int[] T) {
if(T.length <= 1){
return new int[T.length];
}else{
//存储数据并不方便,因为还要得到数组下标,因此不如直接存储下标
Stack stack = new Stack<>();
int[] answer = new int[T.length];
for(int i = 0;i < T.length;i ++){
while(! stack.isEmpty() && T[i] > T[stack.peek()]){
answer[stack.peek()] = i - stack.peek();
stack.pop();
}
stack.push(i);
}
return answer;
}
}
}
解法:见注释
class Solution {
public int[][] reconstructQueue(int[][] people) {
//按照身高递减,身高相同排名递增的顺序重新排列二维数组
Arrays.sort(people,new Comparator(){
public int compare(int[] a,int[] b){
return a[0] == b[0] ? a[1] - b[1] : b[0] - a[0];
}
});
List list = new LinkedList<>();
for(int[] p : people){
//在list的指定下标插入数据
list.add(p[1],p);
}
return list.toArray(new int[people.length][2]);
}
}
解法:HashMap+LinkedList
HashMap表示key是否存在,LinkedList模拟队列
class LRUCache {
public int capacity;
public HashMap map;
public LinkedList list;
public LRUCache(int capacity) {
this.capacity = capacity;
map = new HashMap<>();
list = new LinkedList<>();
}
public int get(int key) {
//
if(map.containsKey(key)){
/*
//使用就把key从list中取出来加到队尾
int index = 0;
for(int i = 0;i < list.size();i ++){
if(list.get(i) == key){
index = i;
break;
}
}
list.remove(index);
list.addLast(key);
*/
//应该注意remove(index)和remove(Object key)的区别
//这里不能直接remove(key)
list.remove((Integer) key);
list.addLast(key);
return map.get(key);
}else{
return -1;
}
}
public void put(int key, int value) {
//如果有key存在也触发使用条件
if(map.containsKey(key)){
list.remove((Integer) key);
list.addLast(key);
map.put(key,value);
}else if(list.size() < capacity){
//长度小于capacity可以put
map.put(key,value);
list.addLast(key);
}else{
map.remove(list.getFirst());
list.removeFirst();
map.put(key,value);
list.addLast(key);
}
}
}
解法:降维,把问题看作XY两个方向的区间合并,不同的是,区间只相交一个点不算相交
class Solution {
public boolean isRectangleOverlap(int[] rec1, int[] rec2) {
if(rec1.length != 4 || rec2.length != 4){
throw new IllegalArgumentException();
}else{
int[] array1 = {rec1[0],rec1[2]};
int[] array2 = {rec2[0],rec2[2]};
int[] array3 = {rec1[1],rec1[3]};
int[] array4 = {rec2[1],rec2[3]};
if(judge(array1,array2) && judge(array3,array4)){
return true;
}else{
return false;
}
}
}
//降维
public boolean judge(int[] array1,int[] array2){
if(array1.length != 2 || array2.length != 2){
return false;
}else{
if(array1[0] <= array2[0]){
//根据题意等于不对
if(array1[1] > array2[0]){
return true;
}
}else{
if(array2[1] > array1[0]){
return true;
}
}
return false;
}
}
}
解法1:双指针,Integer.toString(int x)可以把x转化为String
class Solution {
public boolean isPalindrome(int x) {
if(x < 0){
return false;
}else if(x < 10){
return true;
}else{
String number = Integer.toString(x);
int left = 0;
int right = number.length() - 1;
while(left < right){
if(number.charAt(left) != number.charAt(right)){
return false;
}else{
left ++;
right --;
}
}
return true;
}
}
}
解法2:数学的方法模拟双指针
class Solution {
public boolean isPalindrome(int x) {
if(x < 0){
return false;
}else if(x < 10){
return true;
}else{
int div = 1;
int tem = x;
//必须是大于等于10
while(tem >= 10){
tem = tem / 10;
div *= 10;
}
//System.out.println(div);
//x >= 10不对,无法解决1000021的情况
while(x > 0){
int left = x % 10;
int right = x / div;
if(left != right){
return false;
}else{
//原来的x除去最高位和最低位
x = (x % div) / 10;
div = div / 100;
}
}
return true;
}
}
}
解法:1.字符串反转,让最低位是个位;2.num1 * num2 = answer,由于999 * 999 = 998901,answer数组的长度是num1的长度加上num2的长度即可。不考虑进位:answer[i+j] += num1[i] * num2[j] =;最后统一进位。
class Solution {
public String multiply(String num1, String num2) {
//999*999=998001
//x位的数乘以y位的数,结果肯定是x+y位的数
if(num1 == null){
return num2;
}else if(num2 == null){
return num1;
}else if(num1.equals("0") || num2.equals("0")){
//不应该用==,应该用.equals()
return "0";
}else{
int[] answer = new int[num1.length() + num2.length()];
/*
int number1;
int number2;
*/
//经过反转之后,个位在0
num1 = reverse(num1);
num2 = reverse(num2);
for(int i = 0;i < num1.length();i ++){
for(int j = 0;j < num2.length();j ++){
//最后统一进位
answer[i + j] += ((num1.charAt(i) - '0') * (num2.charAt(j) - '0'));
/*
answer[i + j] += (number1 * number2) % 10;
answer[i + j + 1] += (number1 * number2) / 10;
*/
}
}
//统一进位,注意一个是等于一个是加等于,并且顺序不能反
for(int i = 0;i < answer.length - 1;i ++){
/*
answer[i] = answer[i] % 10;
answer[i + 1] += answer[i] / 10;
*/
answer[i + 1] += answer[i] / 10;
answer[i] = answer[i] % 10;
}
StringBuilder sb = new StringBuilder();
int i = 0;
for(i = answer.length - 1;i >= 0;i --){
if(answer[i] != 0){
break;
}
}
for(;i >= 0;i --){
sb.append(answer[i]);
}
return sb.toString();
}
}
//反转字符串函数
public String reverse(String num){
if(num == null){
return null;
}else{
StringBuilder sb = new StringBuilder();
for(int i = num.length() - 1;i >= 0;i --){
sb.append(num.charAt(i));
}
return sb.toString();
}
}
}
解法:快慢指针+双指针,剑指offer23,链表中环的入口节点
//解法:快慢指针+双指针
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode node = getNode(head);
//面试写的时候,就是忘记判断node == null,导致NullPointerException
if(node == null) {
return null;
}else {
ListNode answer = head;
int length = getLength(node);
//让front先向前走length步,answer和front一起往后一次走一步
ListNode front = head;
for(int i = 0;i < length;i ++) {
front = front.next;
}
while(answer != front) {
answer = answer.next;
front = front.next;
}
return answer;
}
}
//如果有环,得到环的长度
public int getLength(ListNode node) {
int answer = 1;
ListNode tem = node.next;
while(node != tem) {
answer ++;
tem = tem.next;
}
return answer;
}
//快慢指针,返回的要么是环中的节点,要么是null
public ListNode getNode(ListNode head) {
if(head == null) {
return null;
}else {
ListNode fast = head.next;
ListNode slow = head;
while(fast != null && fast.next != null) {
if(fast == slow) {
return fast;
}
slow = slow.next;
fast = fast.next.next;
}
return null;
}
}
}
解法:1+...+n减去nums数组之和,但是直接求nums数组之和,可能会int溢出。
class Solution {
//直接求nums数组的和可能会溢出
public int missingNumber(int[] nums) {
if(nums.length == 0){
throw new IllegalArgumentException();
}else{
int sum = 0;
for(int i = 0;i < nums.length;i ++){
sum += nums[i];
}
return nums.length * (nums.length + 1) / 2 - sum;
}
}
}
class Solution {
//直接求nums数组的和可能会溢出
public int missingNumber(int[] nums) {
if(nums.length == 0){
throw new IllegalArgumentException();
}else{
/*
int sum = 0;
for(int i = 0;i < nums.length;i ++){
sum += nums[i];
}
return nums.length * (nums.length + 1) / 2 - sum;
*/
//原理和上面的一样,但是避免了int溢出
int result = 0;
for(int i = 1;i <= nums.length;i ++){
result += i - nums[i - 1];
}
}
}
}
解法:存储答案的Stringbuilder的先存储个位,并且两个数都从低位相加
class Solution {
//存储答案的Stringbuilder的先存储
public String addBinary(String a, String b) {
if(b == null || b.equals("0")){
return a;
}else if(a == null || a.equals("0")){
return b;
}else{
int index1 = a.length() - 1;
int index2 = b.length() - 1;
int number = 0;
int sum = 0;
StringBuilder sb = new StringBuilder();
while(index1 >= 0 && index2 >= 0){
sum = number + (a.charAt(index1) - '0') + (b.charAt(index2) - '0');
number = sum / 2;
sb.append(sum % 2);
index1 --;
index2 --;
}
while(index1 >= 0){
sum = (a.charAt(index1) - '0') + number;
number = sum / 2;
sb.append(sum % 2);
index1 --;
}
while(index2 >= 0){
sum = (b.charAt(index2) - '0') + number;
number = sum / 2;
sb.append(sum % 2);
index2 --;
}
if(number != 0){
sb.append(number);
}
return sb.reverse().toString();
}
}
}
异或运算的思路见解析:https://leetcode-cn.com/problems/missing-number/solution/que-shi-shu-zi-by-leetcode/
class Solution {
//异或是逐位异或的,比如0^3=3
public int missingNumber(int[] nums) {
int answer = 0;
for(int i = 0;i < nums.length;i ++){
answer ^= (i ^ nums[i]);
}
return answer ^ nums.length;
}
}
解法:哔哩哔哩笔试题,原来用动态规划写的,动态规划不适合{}{}{}()情况,只适合{({[]})}情况,应该用栈。
class Solution {
public boolean isValid(String s) {
if(s.length() == 0){
return true;
}else if(s.length() % 2 == 1) {
return false;
}else {
HashMap map = new HashMap<>();
map.put(')','(');
map.put('}','{');
map.put(']','[');
Stack stack = new Stack<>();
for(int i = 0;i < s.length();i ++){
char c = s.charAt(i);
if(! map.containsKey(c)){
stack.push(c);
}else{
if(! stack.isEmpty() && stack.peek() == map.get(c)){
stack.pop();
}else{
return false;
}
}
}
return stack.isEmpty();
/*
map.put('(',1);
map.put(')',-1);
map.put('[',2);
map.put(']',-2);
map.put('{',3);
map.put('}',-3);
Stack stack = new Stack<>();
for(int i = 0;i < s.length();i ++){
if(! map.containsKey(s.charAt(i))){
return false;
}else if(map.get(s.charAt(i)) > 0){
stack.push(s.charAt(i));
}else{
if(! stack.isEmpty()
&& (map.get(s.charAt(i)) + map.get(stack.peek()) == 0)){
stack.pop();
}else{
return false;
}
}
}
if(stack.isEmpty()){
return true;
}else{
return false;
}
*/
}
}
}
时间复杂度题目要求O(n),空间复杂度O(1)
解法1:反转数组,因此本题改成反转链表也是可以的。
k = k % nums.length,先反转[0,nums.length - 1],再反转[0,k - 1]和[k,nums.length - 1]
class Solution {
public void rotate(int[] nums, int k) {
if(nums.length <= 1){
return;
}else{
//忘记写下面一句
k = k % nums.length;
reverse(nums,0,nums.length - 1);
reverse(nums,0,k -1);
reverse(nums,k,nums.length - 1);
}
}
public void reverse(int[] nums,int left,int right){
int tem = 0;
//当left = right的情况下,循环结束
//当一开始的时候,left = right,不需要反转
while(left < right){
tem = nums[left];
nums[left] = nums[right];
nums[right] = tem;
//忘记写下面的两句了
left ++;
right --;
}
}
}
解法2:https://leetcode-cn.com/problems/rotate-array/solution/xuan-zhuan-shu-zu-by-leetcode/
class Solution {
public void rotate(int[] nums, int k) {
if(nums.length <= 1 || k < 1){
return;
}else{
//忘记写下面一句
k = k % nums.length;
//counter表示已经交换的个数
int counter = 0;
int index = 0;
int start = 0;
int pre;
int tem = 0;
while(counter < nums.length){
index = start;
pre = nums[start];
do{
int next = (index + k) % nums.length;
tem = nums[next];
nums[next] = pre;
pre = tem;
index = next;
next = (next + k) % nums.length;
counter ++;
} while(index != start);
start = (start + 1) % nums.length;
}
}
}
}
解法:哈希表
class Solution {
public int longestPalindrome(String s) {
if(s.length() == 0 && s.length() == 1) {
return s.length();
}else {
HashMap map = new HashMap<>();
int answer = 0;
for(int i = 0;i < s.length();i ++) {
if(map.containsKey(s.charAt(i))) {
map.put(s.charAt(i), map.get(s.charAt(i)) + 1);
}else {
map.put(s.charAt(i), 1);
}
}
for(char key : map.keySet()){
answer += map.get(key) % 2;
}
return answer == 0 ? s.length() : s.length() - answer + 1;
}
}
}
解法:类似于337. 打家劫舍 III
class Solution {
//flag表示题目所给的树是不是平衡二叉树,其值为false就表示不是平衡二叉树
boolean flag = true;
public boolean isBalanced(TreeNode root) {
if(root == null) {
return true;
}else {
//最终目的不是为了获得dp函数的返回值,因此直接调用即可
dp(root);
return flag;
}
}
//dp函数返回的数组,第一个元素表示左子树的高
//第二个元素表示右子树的高
public int[] dp(TreeNode root) {
int[] answer = new int[2];
//root为空直接返回
//flag为false,表示题目中的树的子树已经失衡,直接返回即可
if(root == null || flag == false) {
return answer;
}else {
int[] left = dp(root.left);
int[] right = dp(root.right);
if(get(left[0],left[1]) > 1 || get(right[0],right[1]) > 1){
flag = false;
}
answer[0] = Math.max(left[0],left[1]) + 1;
answer[1] = Math.max(right[0],right[1]) + 1;
if(get(answer[0],answer[1]) > 1){
flag = false;
}
return answer;
}
}
public int get(int a,int b){
return Math.abs(a - b);
}
}
解法:辅助栈和数据栈,两个栈包含元素的数量一直一样
class MinStack {
//辅助栈存储的元素的多少每时每刻都和数据栈一样
//辅助栈的栈顶元素对应数据栈从栈底到栈顶的最小值
public Stack datastack;
public Stack helpstack;
/** initialize your data structure here. */
public MinStack() {
this.datastack = new Stack<>();
this.helpstack = new Stack<>();
}
public void push(int x) {
//加入辅助栈的条件:1.辅助栈为空或者x小于辅助栈栈顶元素
//2.否则,也就是辅助栈不为空并且栈顶元素小于x,那么辅助栈加入栈顶元素
if(helpstack.isEmpty() || x < helpstack.peek()) {
helpstack.push(x);
}else {
helpstack.push(helpstack.peek());
}
//加入数据栈
datastack.push(x);
}
public void pop() {
if(! datastack.isEmpty() && ! helpstack.isEmpty()) {
datastack.pop();
helpstack.pop();
}
}
public int top() {
return datastack.peek();
}
public int min() {
return helpstack.peek();
}
}
解法:设置一个counter = 1和number = nums[0],往后遍历,当遍历得到的数字等于number,counter ++;否则counter --。如果counter == 0,那么number = 当前遍历的数字,counter重新设置为1.
class Solution {
public int majorityElement(int[] nums) {
if(nums.length == 0) {
throw new IllegalArgumentException();
}else if(nums.length == 1) {
return nums[0];
}else {
int counter = 1;
int number = nums[0];
for(int i = 1;i < nums.length;i ++) {
if(nums[i] == number) {
counter ++;
}else {
counter --;
}
if(counter == 0) {
number = nums[i];
counter = 1;
}
}
return number;
}
}
}