剑指Offer(一):二维数组中的查找
//二分查找
public class Solution {
public boolean Find(int target, int [][] array) {
if(array.length==0||array==null){
return false;
}
for(int i=0;i<array.length;i++){
int begin=0;
int end=array[i].length-1;
while(begin<=end){
int mid=(begin+end)/2;
if(target==array[i][mid]){
return true;
}else if(target<array[i][mid]){
end=mid-1;
}else if(target>array[i][mid]){
begin=mid+1;
}
}
}
return false;
}
}
//观察规律
public class Solution {
public boolean Find(int target, int [][] array) {
int row=0;
int col=array[0].length-1;
while(row<array.length&&col>=0){
if(array[row][col]==target){
return true;
}else if(target>array[row][col]){
row++;
}else if(target<array[row][col]){
col--;
}
}
return false;
}
}
剑指Offer(六):旋转数组的最小数字
//参考剑指offer ,将数组分为两个子数组
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
//二分查找
if(array.length==0||array==null){
return 0;
}
int start=0;
int end=array.length-1;
int mid=0;
while(array[start]>=array[end]){
if(end-start==1){
return array[end];
}
mid=start+(end-start)/2;
if(array[mid]>=array[start]){
start=mid;
}else{
end=mid;
}
}
return array[mid];
}
}
剑指Offer(十三):调整数组顺序使奇数位于偶数前面
//两个数组,时间换空间
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param array int整型一维数组
* @return int整型一维数组
*/
public int[] reOrderArray (int[] array) {
ArrayList<Integer> oddList = new ArrayList<>();
ArrayList<Integer> evenList = new ArrayList<>();
int[] res = new int[array.length];
for (int i = 0; i < array.length; i++) {
if (0 == array[i] % 2) {
// 偶数
evenList.add(array[i]);
} else {
// 奇数
oddList.add(array[i]);
}
}
for (int i = 0; i < oddList.size(); i++) {
res[i] = oddList.get(i);
}
int index = oddList.size();
for (int i = 0; i < evenList.size(); i++) {
res[index] = evenList.get(i);
index++;
}
return res;
}
}
//解题思路
/*(O(n),O(n))
遍历两次数组,第一次只添加奇数到新数组里,第二次只添加奇数到新数组里
*/
public int[] reOrderArray (int[] array) {
int index = 0;
int[] res = new int[array.length];
for (int i : array) {
if (i % 2 != 0) {
res[index] = i;
index++;
}
}
for (int i : array) {
if (i % 2 == 0) {
res[index] = i;
index++;
}
}
return res;
}
核心的解法:头尾指针,类似快排的方法
class Solution {
public int[] exchange(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
while (left < right && nums[left] % 2 != 0) {
left++;
}
while (left < right && nums[right] % 2 == 0) {
right--;
}
if (left < right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
}
return nums;
}
}
剑指Offer(二十八):数组中出现次数超过一半的数字
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
HashMap<Integer,Integer> list=new HashMap<Integer,Integer>();
for(int i=0;i<array.length;i++){
if(!list.containsKey(array[i])){
list.put(array[i],1);
if(2>array.length){
return array[i];
}
}else{
int count=list.get(array[i]);
count++;
if(count*2>array.length){
return array[i];
}
list.put(array[i],count);
}
}
return 0;
}
}
import java.util.Arrays;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
Arrays.sort(array);
int count=0;
for(int i=0;i<array.length;i++){
if(array[i]==array[array.length/2]){
count++;
}
}
if(count>array.length/2){
return array[array.length/2];
}else{
return 0;
}
}
}
冒泡排序:
public int[] reOrderArray (int[] array) {
// write code here
int[] result = new int[array.length];
for (int i = 0; i < array.length; i ++) {
for (int j = 0; j < array.length-i-1; j ++) {
if (array[j]%2 == 0 && array[j+1]%2 == 1) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
return array;
}
剑指Offer(三十):连续子数组的最大和
暴力破解方法
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
ArrayList<Integer> list=new ArrayList<Integer>();
for(int i=0;i<array.length;i++){ /这个方法使用暴力破解
int sum=0; /ArrayList的使用
for(int j=i;j<array.length;j++){ / 得到大小用size;
sum+=array[j]; //得到某个值,用get(X)坐标
list.add(sum);
}
}
if(list.size()<0){
return 0;
}
Collections.sort(list);
return list.get(list.size()-1);
}
}
///分析数组规律的方法
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
if(array==null||array.length==0){
return 0;
}
int maxValue=0x80000000;
int countValue=0;
for(int i=0;i<array.length;i++){
if(countValue<=0){
countValue=array[i];
}else{
countValue+=array[i];
}
if(countValue>maxValue){
maxValue=countValue;
}
}
return maxValue;
}
}
剑指Offer(三十二):把数组排成最小的数
暴力破解: 比较 两个字符串的大小 s1>s2
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;
}
}
剑指Offer(三十五):数组中的逆序对
归并排序
public class Solution {
public int InversePairs(int [] array) {
if(array.length==0||array==null){
return 0;
}
int[] copyArray=new int[array.length];
int count=InversePairs(array,copyArray,0,array.length-1);
return count;
}
public int InversePairs(int[] array,int[] copyArray,int low,int high){
if(low==high)
return 0;
int mid=low+(high-low)/2;
int i=mid;
int j=high;
int localCopy=high;
int count=0;
int leftCount=InversePairs(array,copyArray,low,mid)%1000000007;
int rightCount=InversePairs(array,copyArray,mid+1,high)%1000000007;
while(i>=low&&j>mid){
if(array[i]>array[j]){
copyArray[localCopy--]=array[i--];
count+=j-mid;
if(count>1000000007){
count=count%1000000007;
}
}else{
copyArray[localCopy--]=array[j--];
}
}
while(i>=low){
copyArray[localCopy--]=array[i--];
}
while(j>mid){
copyArray[localCopy--]=array[j--];
}
for(int k=low;k<=high;k++){
array[k]=copyArray[k];
}
return (leftCount+rightCount+count)%1000000007;
}
}
剑指Offer(三十七):数字在排序数组中出现的次数
简单做法
public class Solution {
public int GetNumberOfK(int [] array , int k) {
int count=0;
for(int i=0;i<array.length;i++){
if(array[i]==k){
count++;
}
}
return count;
}
}
二分查找
二分查找,参考剑指Offer,但是用的非递归。
public class Solution {
public int GetNumberOfK(int[] array,int k){
if(array==null||array.length==0)
return 0;
int first=getFirstK(array,k,0,array.length-1);
int last=getLastK(array,k,0,array.length-1);
if(first==-1 ||last==-1){
return 0;
}
else{
return last-first+1;
}
}
public int getFirstK(int[] array,int k,int start,int end){
while(start<=end){
int mid=(start+end)/2;
if(k<array[mid])
end=mid-1;
else if(k>array[mid])
start=mid+1;
else{
if((mid>0&&array[mid-1]!=k)||mid==0)
return mid;
else{
end=mid-1;
}
}
}
return -1;
}
public int getLastK(int[] array,int k ,int start,int end){
while(start<=end){
int mid=(start+end)/2;
if(k<array[mid])
end=mid-1;
else if(k>array[mid])
start=mid+1;
else{
if((mid<array.length-1&&array[mid+1]!=k)||mid==array.length-1)
return mid;
else{
start=mid+1;
}
}
}
return -1;
}
}
剑指Offer(四十):数组中只出现一次的数字
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param array int整型一维数组
* @return int整型一维数组
*/
public int[] FindNumsAppearOnce (int[] array) {
// write code here
Map<Integer,Integer> map=new HashMap<Integer,Integer>();
for(int i=0;i<array.length;i++){
if(map.containsKey(array[i])){
map.put(array[i],map.get(array[i])+1);
}else{
map.put(array[i],1);
}
}
int[] res=new int[2];
int index=0;
for(Map.Entry<Integer,Integer> entry:map.entrySet()){
if(entry.getValue()==1){
res[index]=entry.getKey();
index++;
}
}
return res;
}
}
剑指Offer(五十):数组中重复的数字
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param numbers int整型一维数组
* @return int整型
*/
public int duplicate (int[] numbers) {
// write code here
HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
for(int i=0;i<numbers.length;i++){
if(map.containsKey(numbers[i])){
map.put(numbers[i],map.get(numbers[i])+1);
}else{
map.put(numbers[i],1);
}
}
for(int i=0;i<numbers.length;i++){
if(map.get(numbers[i])>1){
return numbers[i];
}
}
return -1;
}
}
如果没有重复数字,那么正常排序后,数字i应该在下标为i的位置,所以思路是重头扫描数组,遇到下标为i的数字如果不是i的话,(假设为m),那么我们就拿与下标m的数字交换。在交换过程中,如果有重复的数字发生,那么终止返回ture
class Solution {
public int findRepeatNumber(int[] nums) {
for(int i=0;i<nums.length;i++){
while (nums[i]!=i){
if(nums[i]==nums[nums[i]]){
return nums[i];
}
int temp=nums[i];
nums[i]=nums[temp];
nums[temp]=temp;
}
}
return -1;
}
}
剑指Offer(五十一):构建乘积数组
通过阶乘构建乘积数组:
import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
if(A==null||A.length==0){
return A;
}
int[] B=new int[A.length];
for(int i=0;i<A.length;i++){
B[i]=Factrial(A,0,i-1)*Factrial(A,i+1,A.length-1);
}
return B;
}
public int Factrial(int[] A,int start,int end){
int temp=1;
for(int i=start;i<=end;i++){
temp=temp*A[i];
}
return temp;
}
}
通过观察规律
import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
if(A==null||A.length==0){
return A;
}
int[] B=new int[A.length];
B[0]=1;
for(int i=1;i<A.length;i++){
B[i]=B[i-1]*A[i-1];
}
int temp=1;
for(int j=A.length-2;j>=0;j--){
temp*=A[j+1];
B[j]*=temp;
}
return B;
}
}
数组左移k位 (不使用额外的空间)
数据结构——数组的循环右移K位算法,仅使用一个附加的空间,交换次数或元素移动时间复杂度为O(n)
数组的循环右移K位算法,仅使用一个附加的空间,交换次数或元素移动时间复杂度为O(n);
/*步骤分为三步:(K=2)
1.将第 1 位至第 N-K 位进行反转;1,2,3, 4,5->3,2,1, 4,5
2.将第 N-K+1 位至第 N 位进行反转;3,2,1, 4,5->3,2,1, 5,4
3.将整个第 1 位至第 N 位进行反转;3,2,1,5,4->4,5,1,2,3
最终即可实现 循环右移 K 位的算法;*/
void Exchange(int Num,int k,int* B)//生成函数
{
k=k%Num;
Reverse(0, Num - k - 1, B);//注意传参时一维数组下标由0开始
Reverse(Num-k, Num-1, B);
Reverse(0, Num - 1, B);
}
void Reverse(int start, int end, int* B)//逆置函数
{
int i = start, j = end, temp = 0;//附加空间
while (i < j)
{
temp = B[i];
B[i] = B[j];
B[j] = temp;
j--;
i++;
}
}