4.二维数组中的查找
题目描述:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
思路:从右上角的数开始比,要是等于就返回true;小于target就row++;大于target就col--,所以列的--应该在最外层循环,满足当前列所对应的那个条件,row++。
public class Solution {
public boolean Find(int target, int [][] array) {
if(array==null||array.length==0||array[0].length==0||array[0][0]>target){
return false;
}
int row=array.length;
int col=array[0].length;
for(int j=col-1;j>=0;j--){
for(int i=0;i<row;i++){
if(array[i][j]==target){
return true;
}else if(array[i][j]>target){
break;
}else{//array[i][j]<target
continue;
}
}
}
return false;
}
}
11.旋转数组的最小数字
题目描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{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;
}
int left=0;
int right=array.length-1;
int mid=left;
while(left<right){
if(right-left==1){
return array[right];
}
mid=(right+left)/2;
if(array[left]==array[right]&&array[right]==array[mid]){
//顺序查找
return findMin(array);
}
//判断Mid位置的数字在前一个递增数组中还是后一个递增数组中
if(array[mid]<array[left]){
//在第二个里面,中间的数小于左边指针指的数
right=mid;
continue;
}else if(array[mid]>array[right]){
//说明在第一个数组里面
left=mid;
continue;
}
}
return array[right];
}
public static int findMin(int[] array){
int min=array[0];
for(int i=0;i<array.length;i++){
if(array[i]<min){
min=array[i];
}
}
return min;
}
}
21.调整数组顺序使奇数位于偶数前面
题目描述:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
思路:一开始想的是用两个指针,一个指向数组开头,然后如果是奇数,就往后移一个位置,如果是偶数,那么就和偶数的指针交换,利用快排思想来实现,但是行不通,因为题目要求保证奇数和奇数,偶数和偶数之间的相对位置不变,即需要是稳定的,那么就需要多申请空间了。两个队列一个放奇数,一个放偶数。
import java.util.Queue;
import java.util.LinkedList;
public class Solution {
public void reOrderArray(int [] array) {
if(array==null||array.length==0){
return;
}
Queue<Integer> odd=new LinkedList<>();
Queue<Integer> even=new LinkedList<>();
for(int i=0;i<array.length;i++){
if(array[i]%2==0){
even.add(array[i]);
}else{
odd.add(array[i]);
}
}
int i=0;
while(!odd.isEmpty()){
array[i]=odd.remove();
i++;
}
while(!even.isEmpty()){
array[i]=even.remove();
i++;
}
}
}
39.数组中出现次数超过一半的数字
题目描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路:一个数字出现次数超过数组长度的一半意味着,把数组进行排序,如果有出现次数超过数组长度一半的数,中位数肯定是我们所求的数字。下面我们就是要看它出现次数是不是超过数组长度的一半,即计算它出现次数,可以参考快排思路。如果超过数组长度一半,那么就返回该数,否则说明不存在,返回0。
import java.util.Arrays;
public class Solution {
public static int MoreThanHalfNum_Solution(int[] array) {
if(array==null||array.length<1){
return 0;
}
Arrays.sort(array);
int mid=array.length/2;
//计算出现次数
int left=mid-1;
int right=mid+1;
int times=1;
while(left>=0){
if(array[left]==array[mid]){
times++;
left--;
continue;
}else{
break;
}
}
while(right<array.length){
if(array[right]==array[mid]){
times++;
right++;
continue;
}else{
break;
}
}
if(times>array.length/2){
return array[mid];
}
return 0;
}
}
42.连续子数组的最大和
题目描述:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)
思路:从数组第一个开始加,如果两个数加起来的结果小于当前max,那么max不变
牛客剑指offer:
1.数组中重复的数字
题目描述:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
思路:hashmap,挨个遍历,没出现过就存进去,出现过就是它!
import java.util.HashMap;
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;
}
HashMap<Integer,Integer> map=new HashMap<>();
for(int i=0;i<numbers.length;i++){
if(map.containsKey(numbers[i])){
duplication[0]=numbers[i];
return true;
}else{
map.put(numbers[i],1);
}
}
return false;
}
}
42.连续子数组的最大和
题目描述:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)。
思路:维护一个累加的和和最大和,如果和小于0的话,那么再往上加后面的不管什么,数都只会更小不会更大,所以如果当前和小于0的话,那么就把当前值设为最大值,否则就往上加。
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
if(array==null||array.length<0){
return 0;
}
int max=array[0];
int current=array[0];
for(int i=1;i<array.length;i++){
//挨个遍历
//current+=array[i];
if(current<0){
current=array[i];
}else{
current+=array[i];
}
if(current>max){
max=current;
}
}
return max;
}
}