剑指offer调整整数数组顺序
题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
public class Solution {
public void reOrderArray(int [] array) {
for(int i=0;i<array.length-1;i++){//遍历数组,遇到左边偶数右边奇数的就调换位置
for(int j=0;j<array.length-1-i;j++){
if(array[j]%2==0&&(array[j+1]&1)==1){
int tmp=array[j];
array[j]=array[j+1];
array[j+1]=tmp;
}
}
}
}
}
顺时针打印矩阵
题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
思想::顺时针打印就是按圈数循环打印,一圈包含两行或者两列,在打印的时候会出现某一圈中只包含一行,要判断从左向右打印和从右向左打印的时候是否会出现重复打印,同样只包含一列时,要判断从上向下打印和从下向上打印的时候是否会出现重复打印的情况。
代码:
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> list = new ArrayList<>();
int row = matrix.length;
int col = matrix[0].length;
if (row == 0 || col == 0) return null;
int top=0,//行数起始
left=0,//列数起始
bottom=row-1,//行数末尾
right=col-1;//列数末尾
while(left<=right&&top<=bottom){
for(int i=left;i<=right;i++){//从左到右
list.add(matrix[top][i]);
}
for(int j=top+1;j<=bottom;j++){//从上到下
list.add(matrix[j][right]);
}
if(top!=bottom)
for(int k=right-1;k>=left;k--){//从右到左
list.add(matrix[bottom][k]);
}
if(left!=right)
for(int l=bottom-1;l>top;l--){//从下到上
list.add(matrix[l][left]);
}
left++;
top++;
right--;
bottom--;
}
return list;
}
}
正则表达式匹配
题目描述
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"aba"均不匹配
思想:先考虑测试用例:模式字符串里包含普通字符、‘.’、‘’;模式字符串和输入字符串匹配/不匹配;特殊:输入字符串和模式字符串为null;
利用字符数组,一定要考虑数组的越界问题,时刻注意,条件表达式角度,要注意划分清楚,
代码:
public class Solution {
public boolean match(char[] str, char[] pattern)
{
if(pattern==null||str==null) return false;
return matchCore(str,0,pattern,0);
}
public boolean matchCore(char[] str,int strIndex, char[] pattern,int patternIndex){
if(strIndex==str.length&&patternIndex==pattern.length) return true;//递归结束条件,两字符串都为空
//模式字符串结束,输入字符串还没结束
if(strIndex!=str.length&&patternIndex==pattern.length)return false;
//模式字符串第二个字符为*且第一个字符串匹配,分三种匹配策略,不匹配则模式移动两位
if(patternIndex+1<pattern.length&&pattern[patternIndex+1]=='*'){
if(strIndex!=str.length&&pattern[patternIndex]==str[strIndex]
||pattern[patternIndex]=='.'&& strIndex != str.length
){//数组越界问题!!!!
return matchCore(str,strIndex+1,pattern,patternIndex+2)
||matchCore(str,strIndex,pattern,patternIndex+2)
||matchCore(str,strIndex+1,pattern,patternIndex);
}else {
return matchCore(str,strIndex,pattern,patternIndex+2);
}
}
if(strIndex!=str.length
&&str[strIndex]==pattern[patternIndex]
||pattern[patternIndex]=='.'){
return matchCore(str,strIndex+1,pattern,patternIndex+1);
}
return false;
}
}
数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
示例1
输入
1,2,3,4,5,6,7,0
输出
7
思想:根据别人的分析把此题当成归并排序,每次考虑先比较相邻的两个数字,则根据归并排序,每次都会有两个已经有序的数组排序到一个辅助数组中去,两个指针分别指向这两个数组的末尾,第三个指针指向辅助数组的末尾;往前遍历,若第一个数组指针指向的数大于第二个数组指针指向的数,则第一个数大于第二个指针往前所有的数。将第一个数放入辅助数组的末尾;
代码:
public class Solution {
public int InversePairs(int [] array) {
if(array==null||array.length==0)
{
return 0;
}
int[] copy = new int[array.length];//辅助数组
int count = InversePairsCore(array,copy,0,array.length-1);//数值过大求余
return count;
}
private int InversePairsCore(int[] array,int[] copy,int low,int high)
{
if(low==high)//递归结束条件(压入栈中的最后入栈条件)
{
return 0;
}
int mid = (low+high)>>1;
int leftCount = InversePairsCore(array,copy,low,mid)%1000000007;
int rightCount = InversePairsCore(array,copy,mid+1,high)%1000000007;
int count = 0;
int i=mid;//两数组的中间位置
int j=high;
int locCopy = high;
while(i>=low&&j>mid)
{
if(array[i]>array[j])
{
count += j-mid;
copy[locCopy--] = array[i--];
if(count>=1000000007)//数值过大求余
{
count%=1000000007;
}
}
else
{
copy[locCopy--] = array[j--];
}
}
for(;i>=low;i--)//如果第一个数组还有剩余,更新到辅助数组中
{
copy[locCopy--]=array[i];
}
for(;j>mid;j--)//同上,第二个数组
{
copy[locCopy--]=array[j];
}
for(int s=low;s<=high;s++)//将已排序的部分更新到原数组中去
{
array[s] = copy[s];
}
return (leftCount+rightCount+count)%1000000007;
}
}
数组中重复的数字
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
思路:因为数组中的值都是小于数组长度的值得,所以可以利用数组的下标值,顺序遍历数组,利用现有数组设置标志,当一个数字被访问过后,可以设置对应位上的数 + n,之后再遇到相同的数时,会发现对应位上的数已经大于等于n了,那么直接返回这个数即可。
代码:
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) {
for(int i = 0;i<length;i++){
int index = numbers[i];
if(index >= length){
index -= length;
}
if(numbers[index] >= length){
duplication[0] = index;
return true;
}else{
numbers[index] += length;
}
}
return false;
}
}