1---数组中重复的数字
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。
也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},
那么对应的输出是第一个重复的数字2。
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 false
public boolean duplicate(int numbers[],int length,int [] duplication) {
if(numbers==null || numbers.length==0){
return false;
}
for(int i=0; i<numbers.length; i++){
if(numbers[i]<0 || numbers[i]>numbers.length-1){
return false;
}
}
for(int j=0; j<numbers.length; j++){
if(numbers[j] != j){
if(numbers[j] == numbers[numbers[j]]){
duplication[0]=numbers[j];
return true;
}
swap(numbers, j, numbers[j]);
}
}
return false;
}
public static void swap(int[] numbers, int i, int j){
int t=numbers[i];
numbers[i]=numbers[j];
numbers[j]=t;
}
}
2---数组中出现次数超过一半的数字
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。
由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
if(array == null || array.length == 0){
return 0;
}
int num=array[0];
int times=1;
for(int j=0; j<array.length; j++){
if(array[j] == num){
times++;
}else{
if(times>0){
times--;
}else{
num=array[j];
times=1;
}
}
}
times=0;
for(int i=0; i<array.length; i++){
if(array[i]==num){
times++;
}
}
if(times>array.length/2){
return num;
}
return 0;
}
}
3--数组中只出现一次的数字
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.*;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if(array == null||array.length ==0){
return;
}
List<Integer> list=new ArrayList<Integer>();
for(int i=0; i<array.length; i++){
if(!list.contains(array[i])){
list.add(array[i]);
}else{
list.remove(new Integer(array[i]));
}
}
if(list.size()==2){
num1[0]=list.get(0);
num2[0]=list.get(1);
}
}
}
添加笔记
4--- 数字在排序数组中出现的次数
统计一个数字在排序数组中出现的次数。
public class Solution {
public int GetNumberOfK(int [] array , int k) {
if(array==null || array.length==0){
return 0;
}
int left=left(array, 0, array.length-1, k);
if(left==-1 ){
return 0;
}
int right=right(array,left, array.length-1, k);
return right-left+1;
}
public static int left(int[] array,int low, int high, int k){
if(array[low]==k){
return low;
}
while(low<=high){
int mid=low+(high-low)/2;
if(mid>=1&&array[mid-1]!=k && array[mid]==k ){
return mid;
}
if(array[mid]>=k){
high=mid-1;
}else{
low=mid+1;
}
}
return -1;
}
public static int right(int[] array, int low, int high, int k){
if(array[high]==k){
return high;
}
while(low<=high){
int mid=low+(high-low)/2;
if(mid<array.length-1&&array[mid+1]!=k && array[mid]==k){
return mid;
}
if(array[mid]>k){
high=mid-1;
}else{
low=mid+1;
}
}
return -1;
}
}
5---
打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
import java.util.ArrayList;
public class Solution {
public String PrintMinNumber(int [] numbers) {
String str = "";
for (int i=0; i<numbers.length; i++){
for (int j=i+1; j<numbers.length; j++){
int a = Integer.valueOf(numbers[i]+""+numbers[j]);
int b = Integer.valueOf(numbers[j]+""+numbers[i]);
if (a > b){
int t = numbers[i];
numbers[i] = numbers[j];
numbers[j] = t;
}
}
}
for (int i = 0; i < numbers.length; i++) {
str += String.valueOf(numbers[i]);
}
return str;
}
}
6---旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,
输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,
若数组大小为0,请返回0。
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
if(array==null || array.length==0){
return 0;
}
if(array.length==1){
return array[0];
}
for(int i=0; i<array.length-1; i++){
if(array[i]>array[i+1]){
return array[i+1];
}
}
return array[0];
}
}
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
if(array == null || array.length ==0)
return 0;
if(array.length == 1)// 一个元素情况
return array[0];
int left = 0;
int right = array.length - 1;
while(left <= right){
int mid = left + ( right - left)/2;// 中间id
if(array[mid] > array[right]){ // 中间元素> 右侧数组的最大值
left = mid + 1;
}else {// 中间元素<= 右侧数组的最大值
if(mid-1>=0 && array[mid-1]>array[mid]){ //左大 右大,中间是最小
return array[mid];
}else
right = mid -1;
}
}
return array[0];// 完全升序情况,上面一直运行 right = mid -1
}
}
7---调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,
所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
public class Solution {
public void reOrderArray(int [] array) {
if(array == null || array.length == 0){
return;
}
for(int i=1; i<array.length; i++){
if(array[i]%2 == 1){
int k=i-1;
int temp=array[i];
while(k>=0 && array[k]%2 ==0){
array[k+1]=array[k];
k--;
}
array[k+1]=temp;
}
}
}
}
8--最小的K个数
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
import java.util.*;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
ArrayList<Integer> list = new ArrayList<>();
if(k > input.length) return list;
Arrays.sort(input);
for (int i = 0; i < k; i ++) {
list.add(input[i]);
}
return list;
}
}
9--
public class Solution {
public int GetUglyNumber_Solution(int index) {
if(index<=0) return 0;
int[] a = new int[index];
int ugly2 = 0;
int ugly3 = 0;
int ugly5 = 0;
a[0] = 1;
int i = 1;
while(i<index) {
int minValue = min(a[ugly2]*2,a[ugly3]*3,a[ugly5]*5);
a[i++] = minValue;
while(a[ugly2]*2<=minValue) ugly2++;
while(a[ugly3]*3<=minValue) ugly3++;
while(a[ugly5]*5<=minValue) ugly5++;
}
return a[index-1];
}
public int min(int a,int b,int c) {
int minValue = a > b ? b : a;
return minValue = minValue> c ? c : minValue;
}
}
10--
public
class
Solution {
public
int
InversePairs(
int
[] array) {
if
(array.length<=
0
)
return
0
;
return
(
int
)(mergeSort(array,
0
,array.length-
1
)%
1000000007
);
}
public
long
mergeSort(
int
[] array,
int
l,
int
r){
if
(l>=r){
return
0
;
}
int
mid=(l+r)/
2
;
long
lnums=mergeSort(array,l,mid)%
1000000007
;
long
rnums=mergeSort(array,mid+
1
,r)%
1000000007
;
return
lnums+rnums+merge(array,l,mid,r);
}
public
long
merge(
int
[] array,
int
l,
int
mid,
int
r){
int
[] temp =
new
int
[r-l+
1
];
long
count=
0
;
int
i=l;
int
j=mid+
1
;
int
t=
0
;
while
(i<=mid && j<=r){
if
(array[i]>array[j]){
// 说明:i - mid 内的数都大于 array[j]
// temp[t++]=array[j];
count+=mid-i+
1
;
// 计算逆序对个数
temp[t++]=array[j++];
// j++;
}
else
{
temp[t++]=array[i];
i++;
}
}
while
(i>mid&&j<=r){
temp[t++]=array[j];
j++;
}
while
(i<=mid&&j>r){
temp[t++]=array[i];
i++;
}
for
(i=l;i<=r;i++){
array[i]=temp[i-l];
}
return
count%
1000000007
;
}
}
11----连续子数组的最大和
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,
常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,
并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。
你会不会被他忽悠住?(子向量的长度至少是1)
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
if(array == null || array.length == 0){
return 0;
}
if(array.length == 1){
return array[0];
}
int res=array[0];
int sum=array[0];
for(int i=1; i<array.length; i++){
res=Math.max(res+array[i], array[i]);
sum=Math.max(res, sum);
}
return sum;
}
}
12----翻转单词顺序列
牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。
同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。
例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,
正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
public class Solution {
public String ReverseSentence(String str) {
if( str == null || str.length()<=0)
return str;
char[] chs = str.toCharArray();
int len = chs.length;
int low = 0;
int high = len - 1;
Reverse(chs,low,high);
low = 0;// 默认单词起始下标
high = 1; // 默认单词结束下标
while(high < len){
// 找到单词结束下标,找到第一个空格,结束后是空格下标
while(high< len && chs[high]!=' ')
high++;
Reverse(chs,low,high-1); // 区间内的单词进行选择
while(high<len && chs[high]==' ') // 过滤掉多余的空格,结束后是非空格下标
high++;
low = high; // 更新起始下标
}
return String.valueOf(chs);
}
public void Reverse(char[] chs,int low ,int high){
while(low < high){
char tmp = chs[low];
chs[low] = chs[high];
chs[high] = tmp;
low++;
high--;
}
}
}
13---求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) {
int sum=n;
boolean bool=(n>0) && ((sum+=Sum_Solution(n-1))>0);
return sum;
}
}
14---不用加减乘除做加法
public class Solution {
public int Add(int num1,int num2) {
int a=num1&num2;
int b=num1^num2;
if(a!=0){
return Add(a<<1,b);
}
return b;
}
}
15--- 整数中1出现的次数(从1到n整数中1出现的次数)
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13
因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
int count=0;
for(int i=1; i<=n; i++){
count+=Count(i);
}
return count;
}
public static int Count(int num){
int count=0;
while(num>0){
if(num%10 ==1){
count++;
}
num/=10;
}
return count;
}
}
16--左旋转字符串
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。
对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,
即“XYZdefabc”。是不是很简单?OK,搞定它!
public class Solution {
public String LeftRotateString(String str,int n) {
if(str == null || str.length() <=1)
return str;
int len= str.length();
n = n%len;
char[] A = str.toCharArray();
reverse(A,0,len-1);
reverse(A,0,len-n-1);
reverse(A,len-n,len-1);
return String.valueOf(A);
}
// 旋转
public void reverse(char[] A,int left, int right){
int i = left;
int j = right;
while(i<j){
swap(A,i,j);
i++;
j--;
}
}
// 交换
public void swap(char[] A,int i,int j){
char ch = A[i];
A[i] = A[j];
A[j] = ch;
}
}
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c
所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
import java.util.ArrayList;
import java.util.*;
public class Solution {
public ArrayList<String> Permutation(String str) {
ArrayList<String> result = new ArrayList<String>();
if(str == null || str.length()==0){
return result;
}
Set<String> set = new TreeSet<String>();
char array[] = str.toCharArray();
Permutation(array,0,set);
result.addAll(set);
return result;
}
public void Permutation(char[] chars,int start,Set<String> set){
if(start == chars.length -1 ){
String p = String.valueOf(chars);
set.add(p);
return;
}
for(int i = start;i<chars.length;i++){
// 交换
swap(chars,start,i);
// 递归
Permutation(chars,start+1,set);
// 换回去
swap(chars,start,i);
}
}
public void swap(char[] array,int i,int j){
char tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
18---- 把字符串转换成整数
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
public class Solution {
public int StrToInt(String str) {
char[] chs = str.toCharArray();
if( !isDigit(chs))
return 0;
int digit = 0;
int k = 0;
boolean flag = true;
if(chs[0]=='+' ) k=1;
if(chs[0]=='-' ){
k = 1;
flag = false;
}
for(int i = k;i<= chs.length -1;i++){
digit = digit * 10 + (chs[i] - '0');
}
if(!flag)
digit = - digit;
return digit;
}
public boolean isDigit(char[] chs){
if(chs == null || chs.length == 0)
return false;
int k = 0;
if(chs[0]=='+' || chs[0] =='-') k=1;
for(int i = k;i< chs.length ;i++)
if(!( '0'<= chs[i] && chs[i] <= '9'))
return false;
return true;
}
}
添加笔记
19--- 第一个只出现一次的字符
在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置
public class Solution {
public int FirstNotRepeatingChar(String str) {
if(str == null || str.length() ==0)
return -1;
int[] A = new int[256];
for(int i=0;i<str.length();i++){
char ch = str.charAt(i);
A[ch]++;
}
for(int i=0;i<str.length();i++){
char ch = str.charAt(i);
if(A[ch] == 1)
return i;
}
return -1;
}
}
20--- 字符流中第一个不重复的字符
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,
第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
import java.util.*;
public class Solution {
//Insert one char from stringstream
// map记录次数,list记录顺序
HashMap<Character,Integer> map = new HashMap<Character,Integer>();
ArrayList<Character> list = new ArrayList<Character>();
public void Insert(char ch)
{
// map 记录个数 2表示多个
if(map.containsKey(ch)){
map.put(ch,2);
}else{
map.put(ch,1);
}
// ArrayList 记录顺序
list.add(ch);
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
for(int i = 0;i<list.size();i++){
if(map.get(list.get(i)) == 1)
return list.get(i);
}
return '#';
}
}
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,
字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
public class Solution {
public boolean isNumeric(char[] str) {
//匹配 带eE的字符串:-1E-16,+123.45e8 。只需要eE后面为整数,eE前是正负整数小数均可
String ePattern = "[+-]?[0-9]*\\.?[0-9]+[eE][+-]?[0-9]+";
// 匹配 不带eE的。 如+123 ,-123,+123.45,-123.45,-0.34
//注:-.123也算数值
String pattern2 = "[+-]?[0-9]*\\.?[0-9]+";
String sss = String.valueOf(str);
return sss.matches(ePattern)
|| sss.matches(pattern2) ;
}
}
22---正则表达式匹配
请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,
而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。
例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
import java.util.Scanner;
public class Solution {
public boolean match(char[] str, char[] pattern){
if(str==null||pattern==null)
return false;
return isMatch(str,0,pattern,0);
}
///三种可能:
//1、模式串当前字符出现0次,即*表示当前字符出现0次,则str=str,pattern=pattern+2;
//2、模式串当前字符出现1次,即*表示当前字符出现1次,则str=str+1,pattern=pattern+2;
//3、模式串当前字符出现2次或2次以上,即*表示当前字符出现2次或以上,则str=str+1,pattern=pattern;
public boolean isMatch(char[] str, int sIndex,char[] pattern,int pIndex){
if(sIndex==str.length&&pIndex==pattern.length)
return true;
if(sIndex!=str.length&&pIndex==pattern.length)
return false;
//排除特例:a和a*a
//由于后面还有一个a所以前面a*需要当作 "0",就算str[]和pattern[]相等,也得舍去,看作不相同
//所以isMatch(str,sIndex,pattern,pIndex+2)这句也需要加上
if(pIndex+1<pattern.length&&pattern[pIndex+1]=='*'){
if(sIndex<str.length&&(str[sIndex]==pattern[pIndex]||pattern[pIndex]=='.'))
return isMatch(str,sIndex,pattern,pIndex+2)|| // 匹配0 个
isMatch(str,sIndex+1,pattern,pIndex+2)|| // 匹配 1 个
isMatch(str,sIndex+1,pattern,pIndex); // 匹配多个,pIndex不变可以继续匹配
else{
return isMatch(str,sIndex,pattern,pIndex+2);// 匹配0 个
}
}
if(sIndex<str.length&&(str[sIndex]==pattern[pIndex]||pattern[pIndex]=='.'))
return isMatch(str,sIndex+1,pattern,pIndex+1);
return false;
}
}
23---从尾到头打印链表
输入一个链表,从尾到头打印链表每个节点的值。
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> result = new ArrayList<Integer>();
Stack<Integer> stack = new Stack<Integer>();
while(listNode!=null){
stack.push(listNode.val);
listNode = listNode.next;
}
while(!stack.isEmpty()){
result.add(stack.pop());
}
return result;
}
}
24---- 合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
public class Solution {
public ListNode Merge(ListNode list1,ListNode list2) {
if(list1 == null){
return list2;
}
if(list2 == null){
return list1;
}
if(list1.val <= list2.val){
list1.next = Merge(list1.next, list2);
return list1;
}else{
list2.next = Merge(list1, list2.next);
return list2;
}
}
}
25--
public class Solution {
public ListNode deleteDuplication(ListNode pHead)
{
if( pHead == null || pHead.next == null)
return pHead;
ListNode head = new ListNode(-1);
head.next = pHead;
ListNode pre = head;
ListNode cur = head;
while( cur!=null){
while(cur.next!=null && cur.val == cur.next.val){
cur = cur.next;
}
if(pre.next == cur) // 开始节点情况
pre = pre.next;
else
pre.next = cur.next;
cur = cur.next;
}
return head.next;
}
}
方法二
public class Solution {
public ListNode deleteDuplication(ListNode pHead)
{
if(pHead == null){
return null;
}
ListNode tmpRoot = new ListNode(-1);
tmpRoot.next = pHead;
ListNode prevNode = tmpRoot;
ListNode curNode = pHead;
while(curNode != null && curNode.next != null){
if(curNode.val == curNode.next.val){
while(curNode.next != null && curNode.next.val == curNode.val){
curNode = curNode.next;
}
prevNode.next = curNode.next;
}else{
prevNode.next = curNode;
prevNode = prevNode.next;
}
curNode = curNode.next;
}
return tmpRoot.next ;
}
}
26--
public class Solution {
public ListNode ReverseList(ListNode head) {
ListNode ReverseHead = null ;//反转之后的头指针
ListNode Node = head;//当前指针
ListNode PreNode = null;//当前指针的前一指针
//处理链表为空以及只有一个结点的情况
if(head == null || head.next == null)
return head;
while(Node != null) {
ListNode nextNode = Node.next;//保存当前结点的下一结点,防止链表截断
if(nextNode == null)
ReverseHead = Node;
Node.next = PreNode ;//将当前链表的next指向前一结点
//后移Node、NextNode,将后面的结点也反转
PreNode = Node;
Node = nextNode ;
}
return ReverseHead;
}
}
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
ListNode fast = head;
ListNode slow = head;
if(k<=0)
return null;
// fast 向前走k步
while(k>=1){
if(fast == null){
return null;
}
fast = fast.next;
k--;
}
// 空的时候说明是第一个结点
if(fast == null ){
return slow;
}
// 一起走
while(fast.next!=null){
fast = fast.next;
slow = slow.next;
}
return slow.next;
}
}
向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链
表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
不用辅助空间的情况下实现O(n)的时间效率。分为三步:第一步复制原始链表上的每一个结点N创建对应的N’,并把N’放在N之后。如下图:
第二步:设置每个结点的random 指针。如果原始链表上的结点N的random指向S,则对应的复制结点N’的random指向S’。
第三步:把长链表分为两个链表:把奇数位置的结点用next连接起来就是原始链表,把偶数位置的结点用next连接起来就是复制出来的链表。
public class Solution {
public RandomListNode Clone(RandomListNode pHead) {
if(pHead == null) {
return null;
}
RandomListNode currentNode = pHead;
//1、复制每个结点,如复制结点A得到A1,将结点A1插到结点A后面;
while(currentNode != null){
RandomListNode cloneNode = new RandomListNode(currentNode.label);
RandomListNode nextNode = currentNode.next;
currentNode.next = cloneNode;
cloneNode.next = nextNode;
currentNode = nextNode;
}
currentNode = pHead;
//2、重新遍历链表,复制老结点的随机指针给新结点,如A1.random = A.random.next;
while(currentNode != null) {
currentNode.next.random = currentNode.random==null?null:currentNode.random.next;
currentNode = currentNode.next.next;
}
//3、拆分链表,将链表拆分为原链表和复制后的链表
currentNode = pHead;
RandomListNode pCloneHead = pHead.next;
while(currentNode != null) {
RandomListNode cloneNode = currentNode.next;
currentNode.next = cloneNode.next;
cloneNode.next = cloneNode.next==null?null:cloneNode.next.next;
currentNode = currentNode.next;
}
return pCloneHead;
}
}
//左神讲的
//先说个定理:两个指针一个fast、一个slow同时从一个链表的头部出发
//fast一次走2步,slow一次走一步,如果该链表有环,两个指针必然在环内相遇
//此时只需要把其中的一个指针重新指向链表头部,另一个不变(还在环内),
//这次两个指针一次走一步,相遇的地方就是入口节点。
//这个定理可以自己去网上看看证明。
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead){
ListNode fast = pHead;
ListNode slow = pHead;
while(fast != null && fast.next !=null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow)
break;
}
if(fast == null || fast.next == null)
return null;
fast = pHead;
while(fast != slow){
fast = fast.next;
slow = slow.next;
}
return fast;
}
}
添加笔记
/*
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 current1 = pHead1;// 链表1
ListNode current2 = pHead2;// 链表2
if (pHead1 == null || pHead2 == null)
return null;
int length1 = getLength(current1);
int length2 = getLength(current2);
// 两连表的长度差
// 如果链表1的长度大于链表2的长度
if (length1 >= length2) {
int len = length1 - length2;
// 先遍历链表1,遍历的长度就是两链表的长度差
while (len > 0) {
current1 = current1.next;
len--;
}
}
// 如果链表2的长度大于链表1的长度
else if (length1 < length2) {
int len = length2 - length1;
// 先遍历链表1,遍历的长度就是两链表的长度差
while (len > 0) {
current2 = current2.next;
len--;
}
}
//开始齐头并进,直到找到第一个公共结点
while(current1!=current2){
current1=current1.next;
current2=current2.next;
}
return current1;
}
// 求指定链表的长度
public static int getLength(ListNode pHead) {
int length = 0;
ListNode current = pHead;
while (current != null) {
length++;
current = current.next;
}
return length;
}
}
import java.util.ArrayList;
import java.util.LinkedList;
public class Solution {
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
ArrayList<Integer> result = new ArrayList<Integer>();
if(root == null)
return result;
while(!queue.isEmpty()){
TreeNode node = queue.poll();
result.add(node.val);
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
return result;
}
}
public class Solution {
public boolean VerifySquenceOfBST(int [] sequence) {
if ( sequence==null || sequence.length<=0 ) return false;
return VerifySquenceOfBST(sequence, 0, sequence.length-1);
}
private boolean VerifySquenceOfBST(int [] sequence, int start, int end){
if ( start>=end )
return true;
int root = sequence[end];
int i=start;
while( sequence[i] < root ){
i++;
}
int j=i;
while( j<end ){
if ( sequence[j]<root ) {
return false;
}
j++;
}
boolean left = VerifySquenceOfBST(sequence, start, i-1);
boolean right = VerifySquenceOfBST(sequence, i, end-1);
return left && right;
}
}
添加笔记
33---二叉树的深度
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
public class Solution {
public int TreeDepth(TreeNode pRoot){
if(pRoot ==null)
return 0;
int nLeft=TreeDepth(pRoot.left);
int nRight=TreeDepth(pRoot.right);
return nLeft>nRight?(nLeft+1):(nRight+1);
}
}
非递归
方法二:非递归
求树的高度,换句话就是求树有多少层,可以参考层次遍历算法,我们只需要记录层数
利用队列
每次队列中保存一层的结点
输出一层元素,加入到下一层元素,深度+1
*
*/
import java.util.*;
public class Solution {
public int TreeDepth(TreeNode pRoot){
if(pRoot ==null)
return 0;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(pRoot);
int depth = 0;
while(!queue.isEmpty()){
int size = queue.size();
depth++;
while(size-- >0){
TreeNode node = queue.poll();
if(node.left!=null)
queue.add(node.left);
if(node.right!=null)
queue.add(node.right);
}
}
return depth;
}
}
34---二叉树中和为某一值的路径
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点
形成一条路径。
import java.util.ArrayList;
/**
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>> rt = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> ls = new ArrayList<>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
if (root==null) return rt;
ls.add(root.val);
if (root.left==null&&root.right==null){
if (root.val==target)
rt.add(new ArrayList<Integer>(ls));
return rt;
}
if (root.left!=null){
FindPath(root.left,target-root.val);
ls.remove(ls.size()-1);}
if (root.right!=null){
FindPath(root.right,target-root.val);
ls.remove(ls.size()-1);}
return rt;
}
}
方法二
import java.util.ArrayList;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
private ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
private ArrayList<Integer> path = new ArrayList<Integer>();
private void dfsFind(TreeNode root, int target){
path.add(root.val); //进入
if(target-root.val == 0 && root.left == null && root.right == null){
result.add(new ArrayList<Integer>(path)); //复制此时的path,并加入到结果路径中
}else {
if(root.left != null) dfsFind(root.left, target-root.val);
if(root.right != null) dfsFind(root.right, target-root.val);
}
path.remove(path.size() - 1); //每次调用函数,有往链表中加入元素,就应该再让他出来,不能影响到其他路径的结果
}
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
if(root != null){
dfsFind(root, target);
}
return result;
}
}
添加笔记
35----平衡二叉树
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
public class Solution {
//后续遍历时,遍历到一个节点,其左右子树已经遍历 依次自底向上判断,每个节点只需要遍历一次
private boolean isBalanced=true;
public boolean IsBalanced_Solution(TreeNode root) {
getDepth(root);
return isBalanced;
}
public int getDepth(TreeNode root){
if(root==null)
return 0;
int left=getDepth(root.left);
int right=getDepth(root.right);
if(Math.abs(left-right)>1){
isBalanced=false;
}
return right>left ?right+1:left+1;
}
}
36---树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
public class Solution {
public static boolean HasSubtree(TreeNode root1, TreeNode root2) {
boolean result = false;
//当Tree1和Tree2都不为零的时候,才进行比较。否则直接返回false
if (root2 != null && root1 != null) {
//如果找到了对应Tree2的根节点的点
if(root1.val == root2.val){
//以这个根节点为为起点判断是否包含Tree2
result = doesTree1HaveTree2(root1,root2);
}
//如果找不到,那么就再去root的左儿子当作起点,去判断时候包含Tree2
if (!result) {
result = HasSubtree(root1.left,root2);
}
//如果还找不到,那么就再去root的右儿子当作起点,去判断时候包含Tree2
if (!result) {
result = HasSubtree(root1.right,root2);
}
}
//返回结果
return result;
}
public static boolean doesTree1HaveTree2(TreeNode node1, TreeNode node2) {
//如果Tree2已经遍历完了都能对应的上,返回true
if (node2 == null) {
return true;
}
//如果Tree2还没有遍历完,Tree1却遍历完了。返回false
if (node1 == null) {
return false;
}
//如果其中有一个点没有对应上,返回false
if (node1.val != node2.val) {
return false;
}
//如果根节点对应的上,那么就分别去子节点里面匹配
return doesTree1HaveTree2(node1.left,node2.left) && doesTree1HaveTree2(node1.right,node2.right);
}
}
37---重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
return root;
}
//前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {
if(startPre>endPre||startIn>endIn)
return null;
TreeNode root=new TreeNode(pre[startPre]);
for(int i=startIn;i<=endIn;i++)
if(in[i]==pre[startPre]){
root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
}
return root;
}
}
38--二叉树的镜像
public class Solution {
public void Mirror(TreeNode root) {
if(root == null)
return;
TreeNode left = root.left;
TreeNode right = root.right;
Mirror(left);
Mirror(right);
root.left = right;
root.right = left;
}
}
public class Solution {
public TreeNode Convert(TreeNode root) {
if(root==null)
return null;
if(root.left==null&&root.right==null)
return root;
// 1.将左子树构造成双链表,并返回链表头节点
TreeNode left = Convert(root.left);
TreeNode p = left;
// 2.定位至左子树双链表最后一个节点
while(p!=null&&p.right!=null){
p = p.right;
}
// 3.如果左子树链表不为空的话,将当前root追加到左子树链表
if(left!=null){
p.right = root;
root.left = p;
}
// 4.将右子树构造成双链表,并返回链表头节点
TreeNode right = Convert(root.right);
// 5.如果右子树链表不为空的话,将该链表追加到root节点之后
if(right!=null){
right.left = root;
root.right = right;
}
return left!=null?left:root;
}
}
40--- 对称的二叉树
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
return isSymmetrical(pRoot,pRoot);
}
boolean isSymmetrical(TreeNode root1,TreeNode root2){
if(root1==null && root2==null)
return true;
if(root1==null || root2==null)
return false;
if(root1.val!=root2.val)
return false;
return isSymmetrical(root1.left,root2.right)
&& isSymmetrical(root1.right,root2.left);
}
}
41--- 按之字形顺序打印二叉树
import java.util.ArrayList;
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<Integer> row = new ArrayList<Integer>();
ArrayList<ArrayList<Integer> > result = new ArrayList<ArrayList<Integer> >();
if(pRoot == null)
return result;
Stack<TreeNode> stack1 = new Stack<TreeNode>();
Stack<TreeNode> stack2 = new Stack<TreeNode>();
boolean flag = true;
stack1.push(pRoot);
while(!stack1.isEmpty() || !stack2.isEmpty()){
row = new ArrayList<Integer>();
if(flag){
int size = stack1.size();
while((size--) >0){
TreeNode node = stack1.pop();
row.add(node.val);
if(node.left!=null)
stack2.push(node.left);
if(node.right!=null)
stack2.push(node.right);
}
flag = false;
}else{
int size = stack2.size();
while((size--) >0){
TreeNode node = stack2.pop();
row.add(node.val);
if(node.right!=null)
stack1.push(node.right);
if(node.left!=null)
stack1.push(node.left);
}
flag = true;
}
result.add(row);
}
return result;
}
}
42---- 把二叉树打印成多行
import java.util.ArrayList;
/*
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 {
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<Integer> row = new ArrayList<Integer>();
ArrayList<ArrayList<Integer> > result = new ArrayList<ArrayList<Integer> >();
if(pRoot == null)
return result;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(pRoot);
while(!queue.isEmpty()){
int size = queue.size();
row = new ArrayList<Integer>();
while((size--)>0){
TreeNode node = queue.poll();
row.add(node.val);
if(node.left!=null)
queue.offer(node.left);
if(node.right!=null)
queue.offer(node.right);
}
result.add(row);
}
return result;
}
}
43--- 二叉搜索树的第k个结点
import java.util.ArrayList;
public class Solution {
ArrayList<TreeNode> list = new ArrayList<TreeNode>();
TreeNode KthNode(TreeNode pRoot, int k)
{
inorder(pRoot);
if(k<=0 || k> list.size())
return null;
return list.get(k-1);
}
public void inorder(TreeNode root){
if(root == null)
return;
inorder(root.left);
list.add(root);
inorder(root.right);
}
}
44---二叉树的下一个结点
/*
思路:
(1) 若该节点存在右子树:则下一个节点为右子树最左子节点(如图节点 B )
(2) 若该节点不存在右子树:这时分两种情况:
2.1 该节点为父节点的左子节点,则下一个节点为其父节点(如图节点 D )
2.2 该节点为父节点的右子节点,则沿着父节点向上遍历,知道找到一个节点的父节点的左子节点为该节点,则该节点的父节点下一个节点(如图节点 I ,沿着父节点一直向上查找找到 B ( B 为其父节点的左子节点),则 B 的父节点 A 为下一个节点)。
*/
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode) {
if (pNode == null)
return pNode;
if (pNode.right != null) { // 节点有右子树
pNode = pNode.right;
while (pNode.left != null) {
pNode = pNode.left;
}
return pNode;
} else if ( pNode.next != null && pNode.next.left == pNode) { // 节点无右子树且该节点为父节点的左子节点
return pNode.next;
} else if (pNode.next != null && pNode.next .right == pNode) { // 节点无右子树且该节点为父节点的右子节点
while(pNode.next != null && pNode .next .left != pNode){
pNode = pNode.next ;
}
return pNode.next ;
}else{
return pNode.next ;//节点无父节点 ,即节点为根节点
}
}
}
45--- 序列化二叉树
/*
算法思想:根据前序遍历规则完成序列化与反序列化。所谓序列化指的是遍历二叉树为字符串;所谓反序列化指的是依据字符串重新构造成二叉树。
依据前序遍历序列来序列化二叉树,因为前序遍历序列是从根结点开始的。当在遍历二叉树时碰到Null指针时,这些Null指针被序列化为一个特殊的字符“#”。
另外,结点之间的数值用逗号隔开。
*/
public class Solution {
int index = -1; //计数变量
String Serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
if(root == null){
sb.append("#,");
return sb.toString();
}
sb.append(root.val + ",");
sb.append(Serialize(root.left));
sb.append(Serialize(root.right));
return sb.toString();
}
TreeNode Deserialize(String str) {
index++;
//int len = str.length();
//if(index >= len){
// return null;
// }
String[] strr = str.split(",");
TreeNode node = null;
if(!strr[index].equals("#")){
node = new TreeNode(Integer.valueOf(strr[index]));
node.left = Deserialize(str);
node.right = Deserialize(str);
}
return node;
}
}
46---
public class Solution {
public boolean Find(int target, int [][] array) {
if(array == null || array.length == 0 || array[0].length == 0){
return false;
}
int row = array.length;
int col = array[0].length;
int i=0; // 行
int j = col - 1; // 列 从右上开始比较
while(i<row && j>= 0){
while(i<row && j>=0){
if(array[i][j] == target){ // 找到
return true;
}else if(array[i][j] >target){// i j 位置元素比较大,应该向小的方向走
j = j - 1;
}else{
i = i + 1;
}
}
}
return false;
}
}
public class Solution {
public String replaceSpace(StringBuffer str) {
int len = str.length();
StringBuffer sb = new StringBuffer();
for(int i=0;i<len;i++){
char ch = str.charAt(i);
if(ch == ' '){
sb.append("%20");
}else{
sb.append(ch);
}
}
return sb.toString();
}
}
public class Solution {
public String replaceSpace(StringBuffer str) {
return str.toString().replaceAll("\\s","%20");
}
}
import java.util.*;
public class Solution {
ArrayList<Integer> list = new ArrayList<Integer>();
public void Insert(Integer num) {
list.add(num);
}
public Double GetMedian() {
int size = list.size();
Collections.sort(list);
if(size%2==1){
return 1.0*list.get(size/2);
}else{
return (list.get(size/2) + list.get(size/2-1))/2.0;
}
}
}
public class Solution {
public int NumberOf1(int n) {
int count = 0;
while(n!=0){
count ++;
n &=(n-1);
}
return count;
}
}
n<=39
public class Solution {
public int Fibonacci(int n) {
int f0 = 0;
int f1 = 1;
int f2 = 1;
if(n <=0)
return f0;
if(n==1)
return f1;
while(n>=2){
f2 = f0 + f1;
f0 = f1;
f1 = f2;
n--;
}
return f1;
}
}
public class Solution {
public int JumpFloor(int target) {
int f0 = 1;
int f1 = 1;
int f2 = 2;
if(target <=0)
return f0;
if(target==1)
return f1;
while(target>=2){
f2 = f0 + f1;
f0 = f1;
f1 = f2;
target--;
}
return f1;
}
}
public class Solution {
public int JumpFloorII(int target) {
if (target <= 0) return 0;
if (target == 1) return 1;
int a = 1;
int b = 2;
for (int i = 2; i <= target; i++) {
b = 2 * a;
a = b;
}
return b;
}
}
public class Solution {
public int JumpFloorII(int target) {
int result = pow(2,target - 1);
return result;
}
public int pow(int a,int b){
if(b<=0)
return 1;
if(b==1)
return a;
int result = pow(a,b/2);
result *=result;
if(b%2==1){
result *=a;
}
return result;
}
}
public class Solution {
public int RectCover(int target) {
if(target<=0)
return 0;
int[] A = new int[target + 1];
A[0] = 1;
A[1] = 1;
for(int i=2;i<=target;i++){
A[i] = A[i-1] + A[i-2];
}
return A[target];
}
}
public class Solution {
public int RectCover(int target) {
if (target < 1) {
return 0;
} else if (target == 1 || target == 2) {
return target;
} else {
return RectCover(target-1) + RectCover(target-2);
}
}
}
public class Solution {
public double Power(double base, int exponent) {
// 指数是 0
if(exponent==0)
return 1.0;
// 底数是 0
if(base ==0)
return 0;
// 指数是 1
if(exponent == 1)
return base;
// 指数为 负
if(exponent <0)
return 1.0/Power(base,-exponent);
//指数是最小值得时候要单独考虑
// if(exponent == Integer.MIN_VALUE){
// return Power(base,exponent+1)/base;
// }
double result = Power(base,exponent/2);
result =result * result;
// 奇数
if((exponent&0x01)==1)
result = result * base;
return result;
}
}
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(!stack2.isEmpty()){
return stack2.pop();
}
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
return stack2.pop();
}
}
添加笔记
import java.util.ArrayList;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA.length == 0 || popA.length == 0)
return false;
if(pushA.length != popA.length)
return false;
ArrayList<Integer> list = new ArrayList<Integer>();
int len = pushA.length;
int j=0;
for(int i=0;i<len;i++){
list.add(pushA[i]);
int k = list.size()-1;
while(k>=0 && j<len && list.get(k) == popA[j]){
list.remove(k);
k--;
j++;
}
}
return j==len;
}
}
添加笔记
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> result = new ArrayList<Integer>();
int len = num.length;
if(size<=0 || size> len)
return result;
for(int i=0;i<len;i++){
int max = Integer.MIN_VALUE;
for(int k=0;k+i < len && k<size;k++){
max = max>num[i+k]?max:num[i+k];
}
result.add(max);
if(i+size==len)
break;
}
return result;
}
}
import java.util.ArrayList;
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> result = new ArrayList<Integer>();
if(num == null || size < 1 || num.length < size)return result;
Deque<Integer> Deque = new LinkedList<>(); //双向队列,用于保存滑动窗口中的数字
//滑动窗口内部,用于判断窗口中的最大值
for(int i = 0; i < size - 1; i++){
while(!Deque.isEmpty() && num[i] > num[Deque.getLast()]){ //getLast为插入端
Deque.removeLast(); //将前面小的直接移除队列,因为不可能成为滑动窗口的最大值
}
Deque.addLast(i); //将当前最大数字存入滑动窗口中
}
//滑动整个窗口
for(int i = size - 1; i < num.length; i++){
while(!Deque.isEmpty() && num[i] > num[Deque.getLast()]){ //getLast为插入端,队尾
Deque.removeLast();
}
Deque.addLast(i);
if(i - Deque.getFirst() + 1 > size){ //getFirst为允许删除端,队头
Deque.removeFirst();
}
result.add(num[Deque.getFirst()]); //每次添加的是num[Deque.getFirst()],而不是Deque.getFirst().
}
return result;
}
}
58----
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
if(matrix == null || rows < 1 || cols < 1 || str == null){//参数校验
return false;
}
boolean[] visit = new boolean[rows*cols];//标记访问过的矩阵坐标位置,初始化为false
for(int i = 0; i < rows; i ++){
for(int j = 0 ;j < cols; j ++){
if(hasPathCore(matrix,rows,cols,i,j,str,0,visit)){
return true;
}
}
}
return false;
}
private boolean hasPathCore(char[] matrix, int rows, int cols, int row,
int col, char[] str, int current, boolean[] visit) {
int index = row*cols + col;
if(row >= rows || col >= cols || row < 0 || col < 0 || visit[index] || matrix[index] != str[current]){
return false;
}
visit[index] = true;//当前k下标的字符匹配成功
if(current == str.length-1){
return true;
}
current ++;//准备匹配下一个字符
if(hasPathCore(matrix, rows, cols, row-1, col, str, current, visit)||//试探当前字符的上方字符
hasPathCore(matrix, rows, cols, row+1, col, str, current, visit)||//试探当前字符的下方字符
hasPathCore(matrix, rows, cols, row, col-1, str, current, visit)||//试探当前字符的左方字符
hasPathCore(matrix, rows, cols, row, col+1, str, current, visit)//试探当前字符的右方字符
){
return true;
}
current --;//如果四个方向的都不对,表明上一个字符匹配不对,回退
visit[index] = false;
return false;
}
public static void main(String[] args) {
char[] matrix = {'a','b','c','e',
's','f','c','s',
'a','d','e','e'};
String str = "abceseecfdas";
Solution offer_66 = new Solution();
System.out.println(offer_66.hasPath(matrix, 3, 4, str.toCharArray()));
}
}
59---- 机器人的运动范围
public class Solution {
int count=0;
public int movingCount(int threshold, int rows, int cols)
{
if(0>threshold || rows<=0 || cols<=0)
return count;
if(threshold ==0)
return 1;
int[][] A = new int[rows][cols]; // 默认是 0
movingCount(A,threshold,0,0,rows,cols);
return count;
}
public void movingCount(int[][] A,int k,int i,int j, int rows, int cols){
if(i<0 || i>= rows || j<0 || j>=cols)
return;
int s = getDigitSum(i,j);
if(s<=k){
if(A[i][j] ==0){
count++;
A[i][j] = 1;
movingCount(A,k,i,j+1,rows,cols);
movingCount(A,k,i,j-1,rows,cols);
movingCount(A,k,i-1,j,rows,cols);
movingCount(A,k,i+1,j,rows,cols);
}
}
}
public int getDigitSum(int a,int b){
return getDigitSum(a) + getDigitSum(b);
}
public int getDigitSum(int num){
int sum = 0;
while(num >0){
sum +=num%10;
num/=10;
}
return sum;
}
}
添加笔记
60-----扑克牌顺子
import java.util.*;
public class Solution {
public boolean isContinuous(int [] numbers) {
if(numbers == null || numbers.length!=5)
return false;
Arrays.sort(numbers);
int flag = 0;
int i = 0;
while(flag<numbers.length && numbers[flag] ==0){
flag++;
}
// falg 就是0 的个数
// 判断剩余数中
// 判断是否有相等元素,有相等则返回false
for(int k = flag;k<numbers.length - 1;k++){
if(numbers[k] == numbers[k+1])
return false;
}
// 判断区间内有几个数
int num = numbers[4] - numbers[flag] ;
return num<=4;
}
}
61---
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if(n == 0 || m == 0)
return -1;
//先构造循环链表
ListNode head = new ListNode(0);//头结点, 值为0
ListNode temp = head;
for(int i = 1; i < n; i++){
temp.next = new ListNode(i); //这里等价head.next = new ListNode(1)
temp = temp.next; //pre不是new出来的,所以pre赋值只是指针改变
}
temp.next = head;//将第n-1个结点(也就是尾结点)指向头结点
temp = head;//temp指向头结点
while(n != 1){
//先找到第m个结点的前驱
for(int i = 1; i < m - 1; i++)//注意从1开始到m-1,注意下标
temp = temp.next;
temp.next = temp.next.next;
temp = temp.next;//更新头结点
n--;
}
return temp.value;
}
}
class ListNode{
int value;
ListNode next = null;
public ListNode(int val){
this.value = val;
}
}
方法二
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if(n<1||m<1)
return -1;
int[] array=new int[n];
for(int i=0;i<n;i++)
array[i]=i;
int i=-1;//用来记录报数的小朋友
int step=0;//用来记录是否报到m
int count=n;//用来记录还剩下多少小朋友
while(count>0){
i++;//小朋友开始报数
if(i==n) i=0;
if(array[i]==-1) continue;//出去已经报过的
step++; //是否到达m
if(step==m){
step=0;
array[i]=-1;
count--;
}
}
return i;
}
}
62---- 顺时针打印矩阵
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> result = new ArrayList<Integer>();
int col = matrix[0].length;
int row = matrix.length;
printMatrix(matrix,col,row,result);
return result;
}
public void printMatrix(int[][] matrix,int col,int row,ArrayList<Integer> result){
//left to right
int startI = 0;
int endI = row - 1;
int startJ = 0;
int endJ = col - 1;
int limit = col>row?col:row;
while(limit-->0){
// 左上 -> 右上
if(startI<=endI && startJ<=endJ){
for(int k = startJ;k<=endJ;k++){
result.add(matrix[startI][k]);
}
startI++;
}
// 右上 -> 右下
if(startI<=endI && startJ<=endJ){
for(int k= startI;k<=endI;k++){
result.add(matrix[k][endJ]);
}
endJ--;
}
// 右下 -> 左下
if(startI<=endI && startJ<=endJ){
for(int k=endJ;k>=startJ;k--){
result.add(matrix[endI][k]);
}
endI--;
}
// 左下 -> 右上
if(startI<=endI && startJ<=endJ){
for(int k=endI;k>=startI;k--){
result.add(matrix[k][startJ]);
}
startJ++;
}
//if(startI>endI || startJ>endJ){
// break;
//}
}
}
}
63----
import java.util.Stack;
public class Solution {
Stack<Integer> stack = new Stack<Integer>();
Stack<Integer> minStack = new Stack<Integer>();
public void push(int node) {
stack.push(node);
if(minStack.isEmpty()){
minStack.push(node);
}else{
int top = minStack.peek();
int min = Math.min(top,node);
minStack.push(min);
}
}
public void pop() {
if(!stack.isEmpty()){
stack.pop();
minStack.pop();
}
}
public int top() {
if(!stack.isEmpty())
return stack.peek();
return -1;
}
public int min() {
if(!minStack.isEmpty())
return minStack.peek();
return -1;
}
}
64---
和为S的连续正数序列
import java.util.ArrayList;
/*
*初始化small=1,big=2;
*small到big序列和小于sum,big++;大于sum,small++;
*当small增加到(1+sum)/2是停止
*/
public class Solution {
public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> lists=new ArrayList<ArrayList<Integer>>();
if(sum<=1){return lists;}
int small=1;
int big=2;
while(small!=(1+sum)/2){ //当small==(1+sum)/2的时候停止
int curSum=sumOfList(small,big);
if(curSum==sum){
ArrayList<Integer> list=new ArrayList<Integer>();
for(int i=small;i<=big;i++){
list.add(i);
}
lists.add(list);
small++;big++;
}else if(curSum<sum){
big++;
}else{
small++;
}
}
return lists;
}
public int sumOfList(int head,int leap){ //计算当前序列的和
int sum=head;
for(int i=head+1;i<=leap;i++){
sum+=i;
}
return sum;
}
}
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
int left = 0;
ArrayList<Integer> result = new ArrayList<Integer>();
int right = array.length - 1;
while(left < right){
int s = array[left] + array[right];
if( s== sum){
result.add(array[left]);
result.add(array[right]);
break;
}else if(s<sum){
left++;
}else{
right--;
}
}
return result;
}
}
import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
if(A==null || A.length <=1)
return A;
int n = A.length;
int[] B = new int[n];
B[0] = 1;
int[] C = new int[n];
C[n-1] = 1;
int[] D = new int[n];
for(int i=0;i< n-1;i++){
B[i+1] = B[i] * A[i];
}
for(int i= n-1;i>=1;i--){
C[i-1] = C[i] *A[i];
}
for(int i=0;i<n;i++){
D[i] = B[i] * C[i];
}
return D;
}
}
添加笔记