文章目录

  • 31、整数中1出现的次数
  • 32、把数组排成最小的数
  • 33、丑数
  • 34、第一个只出现一次的字符
  • 35、数组中的逆序对
  • 36、两个链表的第一个公共结点
  • 37、数字再升序数组中出现的次数
  • 38、二叉树的深度
  • 39、平衡二叉树
  • 40、数组中只出现一次的数字
  • 41、和为S的连续正数序列
  • 42、和为S的两个数字
  • 43、左旋转字符串
  • 44、反转单词顺序列
  • 45、扑克牌顺子
  • 46、孩子们的游戏
  • 47、求1+2+3+...+n
  • 48、不用加减乘除做加法
  • 49、把字符串转化成整数
  • 50、数组中重复的数字
  • 51、构建乘积数组
  • 52、正则表达式匹配
  • 53、表示数值的字符串
  • 54、字符流中第一个不重复的字符
  • 55、链表中入口的结点
  • 56、删除链表中重复的结点
  • 57、二叉树的下一个结点
  • 58、对称的二叉树
  • 59、按之字形顺序打印二叉树
  • 60、把二叉树打印成多行
  • 61、序列化二叉树
  • 62、二叉搜索树的第K个结点
  • 63、数据流中的中位数
  • 64、滑动窗口的最大值
  • 65、矩阵中的路径
  • 66、机器人的运动范围
  • 67、剪绳子

31、整数中1出现的次数

求出1 ~ 13的整数中1出现的次数,并算出100~ 1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

思路:

public class Solution {public int NumberOf1Between1AndN_Solution(int n) {int count=0;for(int i=1;i<=n;i*=10) {int a=n/i,b=n%i;count+=(a+8)/10*i+((a%10==1)?b+1:0);}return count;}
}

32、把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

思路:把数组进行升序排列 例如:123 132 拼接 123132肯定比 132123小,所以123排在132的前面

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;public class Solution {public String PrintMinNumber(int [] numbers) {if(numbers == null || numbers.length == 0) {return "";}String[] strNumbers = new String[numbers.length];for(int i = 0; i < numbers.length; i++) {strNumbers[i] = String.valueOf(numbers[i]);}Arrays.sort(strNumbers, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return (o1 + o2).compareTo(o2 + o1);}});StringBuilder sb = new StringBuilder();for(int i = 0; i < strNumbers.length; i++) {sb.append(strNumbers[i]);}return sb.toString();}
}

33、丑数

把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

public class Solution {public int GetUglyNumber_Solution(int index) {if(index<=0) return 0;int[] data = new int[index];// 初始化第1个data[0] = 1;// 3个指针int p_2 = 0;int p_3 = 0;int p_5 = 0;// 遍历生成for(int i=1;i<index;++i){// 新的丑数int min_ = Math.min(data[p_2]*2,Math.min(data[p_3]*3,data[p_5]*5));// 指针们更新if(data[p_2]*2==min_) p_2++;if(data[p_3]*3==min_) p_3++;if(data[p_5]*5==min_) p_5++;data[i] = min_;}//System.out.println(Arrays.toString(data));return data[index-1];}
}

34、第一个只出现一次的字符

在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)

public class Solution {public int FirstNotRepeatingChar(String str) {int[] num = new int[128];char[] charArray = str.toCharArray();for(int i = 0;i<charArray.length;i++) {num[(int)charArray[i]]++;}for(int i = 0;i<charArray.length;i++) {if(num[(int)charArray[i]] == 1) {return i;}}return -1;}
}

35、数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。
即输出P%1000000007 输入描述: 题目保证输入的数组中没有的相同的数字

数据范围:

对于%50的数据,size<=10^4

对于%75的数据,size<=10^5

对于%100的数据,size<=2*10^5

思路:使用归并排序
这道题最经典的思路是使用分治法计算,借助“归并排序”的分治思想,排好序以后,逆序对就求出来了,时间复杂度为O(nlogn) 。下面举例说明:例如:前有序数组:[2,3,5,8],后有序数组:[4,6,7,12]。

做归并的时候,步骤如下:

第 1 步, 2先出列, 2比“后有序数组”中所有的元素都小,构成“顺序对”;

第 2 步,3 出列, 3比“后有序数组”中所有的元素都小,构成“顺序对”;

第 3 步, 4出列,关键的地方在这里,“前有序数组”中所有剩下的元素[5,8]比 都大,构成2个 “逆序对”;

第 4 步, 5出列, 5比“后有序数组”中所有剩下的元素都小,构成“顺序对”;

第 5 步, 6出列,“前有序数组”中所有剩下的元素[8] 比 6都大,构成 1个“逆序对”

第 6 步, 7出列,“前有序数组”中所有剩下的元素[8]比7都大,构成1个“逆序对”;

第 7 步, 8出列,8 比“后有序数组”中所有剩下的元素[8]都小,构成1个“顺序对”;

第 8 步, 12出列,此时“前有序数组”为空。

因此,我们只需要在“前有序数组”非空,且“后有序数组”中有元素出列的时候,即上面的第 3、5、6 步计算“逆序对”就可以了。

import java.util.*;
public class Solution {//用于记录逆序对static int count = 0;int[] aux = null;public int InversePairs(int [] array) {aux = array.clone();//使用二路归并排序mergeSort(array, 0, array.length-1);return count;}public void mergeSort(int[] array,int low,int height) {if(low>=height) {return;}//使用二路归并排序int mid = low+(height-low)/2;//左边归并mergeSort(array, low, mid);//右边归并mergeSort(array, mid+1, height);//两个有序数组的归并merge1(array,low,mid,height);}public void merge1(int[] a,int low,int mid,int hight) {int i=low,j=mid+1;for(int k=low;k<=hight;k++) {if(i>mid) {a[k]=aux[j++];}else if(j>hight) {a[k]=aux[i];i++;}else if(aux[j]<aux[i]) {a[k]=aux[j];count+=mid-i+1;if(count>1000000007){count %= 1000000007;}j++;}else {a[k]=aux[i++];}}for(int k=low;k<=hight;k++) {aux[k] = a[k];}
//      System.out.println();
//      for(int aa:a) {//          System.out.print(aa+" ");
//      }
//      System.out.println();
//      for(int ii=0;ii<a.length;ii++) {//          if(ii>=low && ii<=hight) {//              System.out.print(a[ii]+" ");
//          }else {//              System.out.print("_ ");
//          }
//      }
//      System.out.print("     "+count);
//      System.out.println();}
}

36、两个链表的第一个公共结点

输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

思路:首先要知道公共结点是什么意思,并不是说数值一样就是公共结点,而实说两个链表从某一个结点开始就合二为一了。所以说,从尾链表开始数起,说明肯定有一端长度相等的链表。我们可以利用这个性质,首先去遍历两个链表,找出两个链表的长度,然后使用双指针,让长度长的链表先走一段距离,等到距离尾结点距离一样的时候,我们再让两个指针一起走,这样就可以判断第一个公共结点

/*
public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}*/
public class Solution {public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {ListNode p1 = pHead1;ListNode p2 = pHead2;int len1 = 0;int len2 = 0;while(p1!=null){len1++;p1 = p1.next;}while(p2!=null){len2++;p2 = p2.next;}while(pHead1!=null && pHead2!=null){if(len1==len2){//两个指针一起走if(pHead1==pHead2){return pHead1;}pHead1 = pHead1.next;pHead2 = pHead2.next;}else if(len1<len2){len2--;pHead2 = pHead2.next;}else if(len1>len2){len1--;pHead1 = pHead1.next;}}return null;}
}

37、数字再升序数组中出现的次数

统计一个数字在升序数组中出现的次数。

思路:用二分法查找某一个值,但是又有点不一样,这个是找某一个值得最左端点,然后从那个位置开始遍历,计算个数

public class Solution {public int GetNumberOfK(int [] array , int k) {if(array.length==0){return 0;}int left = 0;int right = array.length;while(left<right){int mid = (left+right)/2;if(array[mid]==k){//如果等于得话,因为我们要找的是最左的端点,//所以我们继续向左边寻找right = mid;}else if(array[mid]>k){right = mid -1;}else if(array[mid]<k){left = mid +1;}}//退出循环为left==right//然后开始遍历int count = 0;for(int i=left;i<array.length;i++){if(array[i]<k){continue;}else if(array[i]==k){count++;}else if(array[i]>k){break;}}return count;}
}

38、二叉树的深度

输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

/**
public class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}
*/
public class Solution {//用于记录最大深度int count = 0;public int TreeDepth(TreeNode root) {dfs(root,0);return count;}public void dfs(TreeNode root,int n){if(root==null){count = count > n ? count:n;return;}dfs(root.left,n+1);dfs(root.right,n+1);}
}

39、平衡二叉树

输入一棵二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树

public class Solution {public boolean IsBalanced_Solution(TreeNode root) {if(root==null){return true;}int left = len(root.left,0);int right = len(root.right,0);return Math.abs(left-right)<=1;}public int len(TreeNode root,int n){if(root==null){return n;}int left = len(root.left,n+1);int right = len(root.right,n+1);return Math.max(left,right);}
}

40、数组中只出现一次的数字

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

思路:如果是只找出出现一次的数字,我们可以相邻两位进行异或的操作,最后的到的就是我们需要的;这个原理就是如果两个相同的数进行异或,一定等于0,0与任何数异或是他本身。而且存在一个交换律,也就是2 ^ 3 ^ 2 = 2 ^ 2 ^3
.
但是这里的找的是两个只出现一次的数字,那么我们依然顺序异或下去,得到的数字就是两个不同的数字的异或结果,那么我们将异或的结果进行分组,例如2(0010)和4(0100)异或的结果是6(0110)那么我们找从右到左的第一位不为0的数,记录下位数,也就是1 。然后我们将数字中的数字按第一位的数位为0或1进行分类,分为两组,此时2和4肯定不在同一组。所以我们就通过分别对两个数组进行异或得到我们需要的两个值

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {if(array==null || array.length<2){return;}int res = 0;for(int num : array){res ^= num;}int index = 0;for(;index<32;index++){if(((res>>index) & 1 )== 1){break;}}num1[0]=0;num2[0]=0;for(int num:array){if(((num>>index)&1)==1)num1[0] ^= num;elsenum2[0] ^= num;}}
}

41、和为S的连续正数序列

小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
.
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序

思路:滑动窗口,记得小学奥数学了一个求连续N项的公式:(首相+末项)*项数/2
如果当前的值小于sum的话,右边界右移
如果房前值等于sum的话,记录,并左边界左移
如果当前值大于sum的话,左边界左移

import java.util.ArrayList;
public class Solution {public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();//滑动窗口法int left = 1;int right = 2;while(left<right && right<sum) {int count = ((left+right)*(right-left+1))/2;if(count==sum) {ArrayList<Integer> child = new ArrayList<>();for(int i=left;i<=right;i++) {child.add(i);}list.add(child);left++;}else if(count<sum) {right++;}else if(count>sum) {left++;}}return list;}
}

42、和为S的两个数字

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:
对应每个测试案例,输出两个数,小的先输出。

思路:抓住题目中说的有序,我们先来想一下
如果使用暴力的话,我们是怎么做的?
首先抓住一个数,遍历剩下的数字,看看加起来是否等于sum,把加起来的结果进行筛选
但是这样的话,我们就没有用到题目中给到的有序这个条件了
我们再来想一下这样一个案例:array = [1,2,3,4,5,6,7,8,9,10],sum=11 的时候,我们使用暴力是不是能找到这样一个结果集
[[1,10],[2,9],[3,8]…]
我们可以观察一下,输出的结果是两个数字的乘积最小,而两个数字差的绝对值越小,则乘积越高,那么相反,两个数的差的绝对值越大,这乘积就越小
综合我们题目中给出的有序,我们可以使用两个指针,分别指向数组前后
如果当前的和为sum的话,那么肯定是最小的,直接返回输出,
如果小于的话,左边界收缩,
如果大于的话,右边界收缩

import java.util.ArrayList;
public class Solution {public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {ArrayList<Integer> list = new ArrayList<>();if(array.length==0 || sum<array[0]){return list;}int left = 0;int right = array.length-1;//使用双指针while(left<right){int count = array[left]+array[right];if(count==sum){list.add(array[left]);list.add(array[right]);return list;}else if(count<sum){left++;}else if(count>sum){right--;}}return list;}
}

43、左旋转字符串

汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
题解 讨论 通过的代码笔记 纠错 收藏

public class Solution {public String LeftRotateString(String str,int n) {if(n==0 || str.length()==0){return str;}int len = str.length();int b = n%len;if(b==0){return str;}else{StringBuilder sb = new StringBuilder(str);String temp = sb.substring(0,b);sb.delete(0,b);sb.append(temp);return sb.toString();}}
}

44、反转单词顺序列

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student.
a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a
student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

public class Solution {public String ReverseSentence(String str) {if(str.length()==0 || str.trim().equals("")){return str;}StringBuilder sb = new StringBuilder();String[] num = str.split(" ");for(int i=num.length-1;i>=0;i--){sb.append(num[i]+" ");}sb.deleteCharAt(sb.length()-1);return sb.toString();}
}

45、扑克牌顺子

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

import java.util.*;
public class Solution {public boolean isContinuous(int [] numbers) {// 0-13 54张if(numbers.length != 5)return false;// 排序Arrays.sort(numbers);// 计算0int zindex = 0;while(numbers[zindex] == 0)zindex++;// 判重复(防止越界)for(int i = zindex+1; i < numbers.length; i++)if(numbers[i-1] == numbers[i]) return false;// 值差判断return numbers[4] - numbers[zindex] <= 4;}
}

46、孩子们的游戏

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
如果没有小朋友,请返回-1

import java.util.*;
public class Solution {public int LastRemaining_Solution(int n, int m) {if(n==0) {return -1;}else if(n==1){return 0;}else{//链表,找规律就完事了List<Integer> list = new ArrayList<>();for(int i=0;i<n;i++){list.add(i);}int start = 0;int count = 0;while(list.size()!=1){int number = (start+m-1)%(n-count);list.remove(number);start = number;count++;}return list.get(0);}}
}

47、求1+2+3+…+n

求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

public class Solution {public int Sum_Solution(int n) {if(n==1){return 1;}return Sum_Solution(n-1)+n;}
}

48、不用加减乘除做加法

写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

public class Solution {public int Add(int num1,int num2) {while(num2!=0){int temp = num1 ^ num2;num2 = (num1 & num2) << 1;num1 = temp;}return num1;}
}

49、把字符串转化成整数

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
输入描述:
输入一个字符串,包括数字字母符号,可以为空
输出描述:
如果是合法的数值表达则返回该数字,否则返回0

public class Solution {public int StrToInt(String str) {int len = str.length();if(len<=0){return 0;}int symbol = 1;if(str.charAt(0)=='-'){symbol = -1;}int res = 0;for(int i = (str.charAt(0)=='+' || str.charAt(0)=='-')?1:0;i<str.length();i++){if(str.charAt(i) >= '0' && str.charAt(i) <= '9'){res = (res << 1) + (res << 3) + (str.charAt(i) & 0xf);}else{return 0;}}return res*symbol;}
}

50、数组中重复的数字

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

import java.util.*;
public class Solution {// Parameters://    numbers:     an array of integers//    length:      the length of array numbers//    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;//                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++//    这里要特别注意~返回任意重复的一个,赋值duplication[0]// Return value:       true if the input is valid, and there are some duplications in the array number//                     otherwise falsepublic boolean duplicate(int numbers[],int length,int [] duplication) {if(length<=1){return false;}Map<Integer,Integer> map = new HashMap<>();for(int i=0;i<length;i++){map.put(numbers[i],map.getOrDefault(numbers[i],0)+1);int num = map.get(numbers[i]);if(num==2){duplication[0] = numbers[i];return true;}}return false;}
}

51、构建乘积数组

给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * … * A[n-1],B[n-1] = A[0] * A[1] * … * A[n-2];)
对于A长度为1的情况,B无意义,故而无法构建,因此该情况不会存在。
题解 讨论 通过的代码笔记 纠错 收藏

import java.util.ArrayList;
public class Solution {public int[] multiply(int[] A) {int[] re = new int[A.length];int temp = 1;for(int i=0;i<A.length;i++){temp = 1;for(int j=0;j<A.length;j++){if(i==j){continue;}else{temp*=A[j];}}re[i] = temp;}return re;}
}

52、正则表达式匹配

请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
题解 讨论 通过的代码笔记 纠错 收藏

public class Solution {public boolean match(char[] str, char[] pattern) {if (str == null || pattern == null) {return false;}boolean[][] dp = new boolean[str.length + 1][pattern.length + 1];//初始化矩阵,相当于初始化最后一列dp[str.length][pattern.length] = true;//boolean[][] dp = initDP(str, pattern);for (int i = str.length; i >= 0; i--) {for (int j = pattern.length - 1; j >= 0; j--) {if (j + 1 == pattern.length || pattern[j + 1] != '*') {dp[i][j] = i != str.length && (str[i] == pattern[j] || pattern[j] == '.') && dp[i + 1][j + 1];continue;}int index = i;while(index < str.length && (str[index] == pattern[j] || pattern[j] == '.')) {if (dp[index + 1][j + 2]) {dp[i][j] = true;break;}index++;}dp[i][j] = dp[i][j] == true ? true : dp[i][j+2];}}return dp[0][0];}
}

53、表示数值的字符串

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

public class Solution {/*** 定义状态机* 0:初始化* 1:符号为  +-* 2:数字* 3:小数点* 4:小数点后数字* 5:e E* 6:e E后符号* 7:e后数字* @param str* @return*/public boolean isNumeric(char[] str) {//如果长度为0的话,直接返回if(str==null || str.length==0) {return false;}//初始化为0int status = 0;for(int i=0;i<str.length;i++) {if(str[i]=='+' || str[i]=='-') {if(status == 0) {status = 1;}else if(status == 5){status = 6;}else {return false;}}else if(str[i]=='e' || str[i]=='E') {if(status==2 || status==4) {status=5;continue;}else {return false;}}else if(str[i]=='.') {if(status==0 || status==1 ||status==2) {status = 3;}else {return false;}}else if(str[i]>='0' && str[i]<='9') {if(status == 3) {status = 4;}else if(status==6) {status = 7;}else if(status == 0||status==1||status==2||status==5) {status = 2;}else if(status==4) {status = 4;}}else {return false;}}return status ==2||status==4||status==7;}
}

54、字符流中第一个不重复的字符

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:
如果当前字符流没有存在出现一次的字符,返回#字符。

public class Solution {/**其实就是存储每一位出现的次数,如果找的话,从前后往后找看看这个字母是否只出现了一次*/int[] hashTable = new int[256];StringBuffer buffer = new StringBuffer();public void Insert(char ch){buffer.append(ch);hashTable[ch]++;}//return the first appearence once char in current stringstreampublic char FirstAppearingOnce(){char[] temp = buffer.toString().toCharArray();for(char ch: temp){if(hashTable[ch] == 1){return ch;}}return '#';}
}

55、链表中入口的结点

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

具体思路请看这位大佬的双指针汇总,强的一批:传送门

/*public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}
*/
public class Solution {public ListNode EntryNodeOfLoop(ListNode pHead){if(pHead.next==null){return null;}ListNode p1 = pHead;ListNode p2 = pHead;while(p1!=null && p2!=null){p1 = p1.next;p2 = p2.next.next;if(p1==p2){break;}}//判断当前的链表有没有结点if(p1!=p2){return null;}p1 = pHead;while(p1!=p2){p1 = p1.next;p2 = p2.next;}return p1;}
}

56、删除链表中重复的结点

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

/*public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}
*/
public class Solution {public ListNode deleteDuplication(ListNode pHead){//使用三指针,去判断当前的位置if(pHead==null){return pHead;}ListNode pre = new ListNode(-1);pre.next = pHead;ListNode cur = pHead;ListNode next = pHead.next;pHead = pre;while(next!=null){//判断当前结点和后一个结点是否一样while(next!=null && cur.val==next.val){next = next.next;}//判断next结点到底有没有继续走下去if(cur.next!=next){//说明存在一样的if(next==null){//如果已经走到了最后了//说明从cur到最后一个都是重复的,删除pre.next = next;break;}else{pre.next = next;cur = next;if(cur.next!=null){next = cur.next;}else{break;}}}else{//说明结点没有重复pre = pre.next;cur = cur.next;next = next.next;}}return pHead.next;}
}

57、二叉树的下一个结点

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

/*
public class TreeLinkNode {int val;TreeLinkNode left = null;TreeLinkNode right = null;TreeLinkNode next = null;TreeLinkNode(int val) {this.val = val;}
}
*/
public class Solution {public TreeLinkNode GetNext(TreeLinkNode pNode){if(pNode==null){return null;}if(pNode.right!=null){return next(pNode.right);}if(pNode.next==null){//又没有右结点,有没有父节点return null;}else{return pre(pNode);}}public TreeLinkNode next(TreeLinkNode pNode){if(pNode.left==null){return pNode;}return next(pNode.left);}public TreeLinkNode pre(TreeLinkNode pNode){TreeLinkNode parent = pNode.next;if(parent==null){return pNode;}//判断左右节点if(parent.left==pNode){return parent;}else{TreeLinkNode p1 = parent.next;while(p1!=null && p1.left!=parent){parent = p1;p1 = p1.next;}return p1;}}
}

58、对称的二叉树

请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

/*
public class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}
*/
public class Solution {boolean isSymmetrical(TreeNode pRoot) {return checker(pRoot, pRoot);}public boolean checker(TreeNode pRoot1, TreeNode pRoot2) {if(pRoot1 == null && pRoot2 != null) {return false;}if(pRoot1 != null && pRoot2 == null) {return false;}if(pRoot1 == null && pRoot2 == null) {return true;}if(pRoot1.val != pRoot2.val) {return false;}return checker(pRoot1.left, pRoot2.right) && checker(pRoot1.right, pRoot2.left);}
}

59、按之字形顺序打印二叉树

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

import java.util.*;/*
public class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}
*/
public class Solution {public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {ArrayList<ArrayList<Integer>> list = new ArrayList<>();if(pRoot==null){return list;}Queue<TreeNode> queue = new LinkedList<>();queue.add(pRoot);int count = 1;boolean flag = true;while(!queue.isEmpty()){ArrayList<Integer> ch = new ArrayList<>();int number = count;count = 0;for(int i=0;i<number;i++){TreeNode node = queue.poll();ch.add(node.val);if(node.left!=null) {queue.add(node.left);count++;}if(node.right!=null) {queue.add(node.right);count++;}}if(!flag) {ch = reverse(ch);}flag = flag==true?false:true;list.add(ch);}return list;}public ArrayList<Integer> reverse(ArrayList<Integer> list){ArrayList<Integer> re = new ArrayList<Integer>();for(int i=list.size()-1;i>=0;i--) {re.add(list.get(i));}return re;}}

60、把二叉树打印成多行

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

import java.util.*;/*
public class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}
*/
public class Solution {ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {ArrayList<ArrayList<Integer>> list = new ArrayList<>();if(pRoot==null){return list;}Queue<TreeNode> queue = new LinkedList<>();queue.add(pRoot);int count = 1;while(!queue.isEmpty()){ArrayList<Integer> ch = new ArrayList<>();int number = count;count = 0;for(int i=0;i<number;i++){TreeNode node = queue.poll();ch.add(node.val);if(node.left!=null) {queue.add(node.left);count++;}if(node.right!=null) {queue.add(node.right);count++;}}list.add(ch);}return list;}}

61、序列化二叉树

请实现两个函数,分别用来序列化和反序列化二叉树

二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过
某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。

二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。

例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己的函数来解析回这个二叉树

/*
public class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}
*/
import java.util.*;
public class Solution {String Serialize(TreeNode root) {//tree:[]//node:,//val:Str(val)//null:"null"StringBuilder res = new StringBuilder("[");Queue<TreeNode> queue = new LinkedList<>();queue.add(root);while(!queue.isEmpty()){TreeNode cur = queue.remove();if(cur==null){res.append("null,");}else{res.append(cur.val+",");queue.add(cur.left);queue.add(cur.right);}}res.setLength(res.length()-1);res.append("]");return res.toString();}TreeNode Deserialize(String str) {String[] nodes = str.substring(1,str.length()-1).split(",");TreeNode root = getNode(nodes[0]);Queue<TreeNode> parents = new LinkedList<>();TreeNode parent = root;boolean isLeft = true;for(int i=1;i<nodes.length;i++){TreeNode cur = getNode(nodes[i]);if(isLeft){parent.left = cur;}else{parent.right = cur;}if(cur!=null){parents.add(cur);}isLeft = !isLeft;if(isLeft){parent = parents.poll();}}return root;}public TreeNode getNode(String val){if(val.equals("null")){return null;}return new TreeNode(Integer.valueOf(val));}
}

62、二叉搜索树的第K个结点

给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

/*
public class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}
*/
public class Solution {TreeNode KthNode(TreeNode pRoot, int k){//莫里斯可遍历TreeNode cur = pRoot;TreeNode pre = null;TreeNode res = null;int count = 0;while(cur!=null){pre = cur.left;if(pre!=null){//进入左子数while(pre.right!=null && pre.right!=cur){pre = pre.right;}if(pre.right==null){pre.right = cur;cur = cur.left;}else{count++;if(count == k){return cur;}pre.right = null;cur = cur.right;}}else{//左节点不存在,进去右子数count++;if(count == k){return cur;}cur = cur.right;}}return res;}}

63、数据流中的中位数

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

import java.util.*;
public class Solution {List<Integer> list = new ArrayList<>();public void Insert(Integer num) {list.add(num);list.sort(new Comparator<Integer>(){public int compare(Integer o1,Integer o2){return o1-o2;}});}public Double GetMedian() {int len = list.size();if(len%2==0){double res = (double)(list.get(list.size()/2) + list.get((list.size()-1)/2))/2;return res;}else{int index = list.size()/2;return (double)list.get(index);}}}

64、滑动窗口的最大值

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
窗口大于数组长度的时候,返回空

import java.util.*;
public class Solution {public ArrayList<Integer> maxInWindows(int [] num, int size){ArrayList<Integer> result = new ArrayList<Integer>();if(num == null || num.length == 0 || size == 0)return  result;LinkedList<Integer> queue = new LinkedList<Integer>();for(int i=0;i<size-1;i++){while(!queue.isEmpty() && num[i] > num[queue.getLast()]){queue.removeLast();}queue.addLast(i);}for(int i=size-1;i<num.length;i++){while(!queue.isEmpty() && num[i] > num[queue.getLast()]){queue.removeLast();}queue.addLast(i);if (i-queue.getFirst()+1 > size)queue.removeFirst();result.add(num[queue.getFirst()]);}return result;}
}

65、矩阵中的路径

public class Solution {public boolean hasPath(char[] matrix, int rows, int cols, char[] str){int[] flag = new int[matrix.length];for(int i = 0; i < rows; i ++){for(int j = 0; j < cols; j ++){if(helper(matrix, rows, cols, i, j, str, 0, flag)){return true;}}}return false;}public static boolean helper(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, int[] flag){int index = i * cols + j;if(i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || flag[index] == 1){//下标不符合,index对应的值不为和字符数组中的不一致,或者该index已经被访问,这些情况只要有符合的就返回false//只有上面的所有情况都不符合,也就是值相等,且没有访问过,下标不符合return false;}if(k == str.length - 1){return true;}flag[index] = 1;if(helper(matrix, rows, cols, i - 1, j, str, k + 1, flag)||helper(matrix, rows, cols, i + 1, j, str, k + 1, flag)||helper(matrix, rows, cols, i, j - 1, str, k + 1, flag)||helper(matrix, rows, cols, i , j + 1, str, k + 1, flag)){return true;}flag[index] = 0;return false;}
}

66、机器人的运动范围

地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

public class Solution {public int movingCount(int threshold, int rows, int cols){if(threshold==0){return 1;}if(threshold<0){return 0;}boolean[][] dp = new boolean[rows][cols];int re = 1;dp[0][0] = true;for(int i=0;i<rows;i++){for(int j=0;j<cols;j++){if((i==0 && j==0) || count(i)+ count(j)>threshold){continue;}if(i-1>=0 && j-1>=0){dp[i][j] = dp[i-1][j] || dp[i][j-1];}else if(i-1>=0){dp[i][j] = dp[i-1][j];}else if(j-1>=0){dp[i][j] = dp[i][j-1];}re += dp[i][j]?1:0;}}return re;}public int count(int num){int re = 0;while(num!=0){re += num%10;num /= 10;}return re;}
}

67、剪绳子

给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
输入描述:
输入一个数n,意义见题面。(2 <= n <= 60)
输出描述:
输出答案。

public class Solution {public int cutRope(int target) {if(target<=3){return target-1;}int a = target/3, b=target%3;if(b==0){return (int)Math.pow(3,a);}else if(b==1){return (int)Math.pow(3,a-1)*4;}else{return (int)Math.pow(3,a)*2;}}
}

剑指offe【31-67】相关推荐

  1. 【LeetCode】剑指 Offer 31. 栈的压入、弹出序列

    [LeetCode]剑指 Offer 31. 栈的压入.弹出序列 文章目录 [LeetCode]剑指 Offer 31. 栈的压入.弹出序列 package offer;import java.uti ...

  2. leetcode剑指offe刷题-第一题-用两个栈实现队列

    leetcode剑指offe刷题-第一题 文章目录 leetcode剑指offe刷题-第一题 前言 一.用两个栈实现队列 1.思路 2.代码如下 总结 前言 记录一下自己刷算法的路程. leetcod ...

  3. 数组中重复的元素(剑指Offe.03)

    数组中重复的元素(剑指Offe.03) 题目描述: 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了 ...

  4. 挑战一天(12h)刷完《剑指offer》67题

    提前说明,挑战的人不是我. 大家周末好,我是爱上 B 站的小吴,最近一段时间我在网站 AlgoMooc 录制剑指 Offer 的视频,同时上传了一部分到 B 站,基于推荐算法,B 站疯狂的给我推送如何 ...

  5. 【剑指 Offe】11. 旋转数组的最小数字

    题目:剑指 Offer 11. 旋转数组的最小数字 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数 ...

  6. 剑指offe 和为S的连续正数序列

    1.题目 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久,他 ...

  7. 剑指Offe 50:数组中重复的数字

    第一种方法:遍历一遍数组,依次放入hash表.一旦遇到一个元素哈希表中已经有了,就是第一个重复的数字. class Solution { public:bool duplicate(int numbe ...

  8. 【剑指 Offe】剑指 Offer 18. 删除链表的节点

    目录标题 算法汇总 题目 关键点 代码 1.解体方法 思路 代码 时间和空间复杂度 2.解题方法,如暴力法 思路 代码 时间和空间复杂度 算法汇总 以下是所有算法汇总,包括GitHub源码地址链接:力 ...

  9. 【剑指 Offe】剑指 Offer 11. 旋转数组的最小数字

    目录标题 算法汇总 题目 关键点 代码 1.解体方法 - 二分法 思路 代码 时间和空间复杂度 2.解题方法,如暴力法 思路 代码 时间和空间复杂度 算法汇总 以下是所有算法汇总,包括GitHub源码 ...

  10. 【剑指 Offe】剑指 Offer 17. 打印从1到最大的n位数

    目录标题 算法汇总 题目 关键点 代码 1.解体方法 思路 代码 时间和空间复杂度 2.解题方法,如暴力法 思路 代码 时间和空间复杂度 算法汇总 以下是所有算法汇总,包括GitHub源码地址链接:力 ...

最新文章

  1. Android Wear 唤醒热词会比“你好,安卓”好吗?
  2. netty系列之:使用netty搭建websocket服务器
  3. 批处理系统和分时系统各具有什么特点?为什么分时系统的响应比较快?
  4. 工作136:eachrt
  5. opencv android
  6. 保证一致性吗_谈了千百遍的缓存数据一致性问题
  7. 2011浙大878计算机专业基础综合大题答案解析
  8. tinycc update VERSION to 0.9.27
  9. paip.提升安全性----软键盘的弱点
  10. windows php_redis.dll 官方下载地址 php5x php7x
  11. eslint 如何关闭检查变量名规范或者大小写检查
  12. Java源文件命名规则
  13. 80C51单片机的四组IO口
  14. 【李沐:动手学深度学习pytorch版】第2章:预备知识
  15. 卡内基·梅隆大学计算机科学系主任周以真的父母是中国人吗,计算思维(Computational Thinking)...
  16. Java_银行开户存取款
  17. matlab 抛物线法求最小值,抛物线法matlab
  18. 网易云音乐评论墙php源码,网易云音乐热评墙那些令人感慨的句子,哪一句打动了你?...
  19. CreateDC与CreateCompatibleDC建立的HDC有何不同?
  20. EOS忘记映射找回教程,EOS公钥映射错误找回教程。

热门文章

  1. TOTP 介绍及基于C#的简单实现
  2. 教你如何给小米5续命
  3. 三角函数对应在平面坐标上画圆
  4. ADC标准 INLDNL(1)
  5. Kubernetes如何被应用在华为
  6. Jenkins流水线部署java项目
  7. 2015年中央电大c语言,2015年电大 2015年电大小抄-中央电大2012春季c语言程序设计期末复习指导(本)资料.doc...
  8. 2021年中国电饭锅(电饭煲)行业现状及前景分析:个性化消费推动市场向高端、智能化发展[图]
  9. 在进化计算中,软件进行元基编码的新陈代谢方式 V0. 1. 0
  10. 米兔机器人第三代测评_米兔智能机器人——年轻人的第一台 31313?