仅有代码
一、数组中重复数组
/**
* 数组中重复的数字
* 在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。
* 数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。
* 请找出数组中任意一个重复的数字。(或输出全部重复数字)
* 例如:
* Input:
* {2, 3, 1, 0, 2, 5}
* Output:
* 2
*/
public class DuplicateArrayNum {
public boolean duplicate(int nums[], int length) {
if(nums == null | length <= 0) {
return false;
}
for(int i=0; i<length; i++) {
while(nums[i] != i) {
if(nums[i] == nums[nums[i]]) {
System.out.println(nums[i] + ", ");
return true;
}
//2,3,1,0,2,1
/*//换位
int t = nums[i];
System.out.println("1、t is : " + t + " nums[i] is :" + nums[i]);
System.out.print("2、 nums[nums[i]] is : " + nums[nums[i]]);
nums[i] = nums[nums[i]];
System.out.println(" nums[i] is :" + nums[i] );
nums[nums[i]] = t;
System.out.println("3、nums[i]" + nums[i] + " nums[nums[i]] is: "+ nums[nums[i]] + " t is:"+ t);*/
/**
* 以上错误原因:
* 分析:第一步: i=0 nums[0]=2 此时 t=2 nums[0]=2
* 第二步: i=0 nums[nums[0]]-> nums[2]=1
* nums[0]=2
* 赋值: nums[0] = (nums[nums[0]] = 1 )
* 即第二步之后:nums[0]=1
*第三步: i=0 nums[nums[0]]->nums[1]=2
* 此时t赋值就发生了错误。
*
* 总结: 因为在第二步nums[0]的值发生了改变,因此在第三步nums[nums[i]]就指向了下标为1的数字,不符合我们期望(下标0和下标2发生数值交换)
* 因此发生错误!
*/
//若向避免错误,必须将下标赋值给提前定义好的变量
int a = nums[i];
int b = nums[nums[i]];
//此时a、b表示的就是将要发生数值交换的数组的下标
//进行数值交换
int t = nums[a];
nums[a] = nums[b];
nums[b] = t;
for(int c=0; c<nums.length; c++) {
System.out.print(nums[c] + " , ");
}
System.out.println();
}
}
return false;
}
public boolean duplicate2(int[] nums, int length) {
if (nums == null || length <= 0)
return false;
for (int i = 0; i < length; i++) {
while (nums[i] != i) {
if (nums[i] == nums[nums[i]]) {
System.out.println(nums[i] + ", ");
return true; //只能查出一个
//break;//使用break可以查询出这个数组中全部有重复的数字
}
swap(nums, i, nums[i]);
}
}
return false;
}
private void swap(int[] nums, int i, int j) {
nums[i] = nums[i] ^ nums[j];
nums[j] = nums[i] ^ nums[j];
nums[i] = nums[i] ^ nums[j];
for(int a=0; a<nums.length; a++) {
System.out.print(nums[a] + " , ");
}
System.out.println();
}
public static void main(String[] args) {
int[] nums = {1,2,3,5,0,2};
new DuplicateArrayNum().duplicate(nums, nums.length);
}
}
二、二维数组的查找
/**
* 二维数组中的查找
* 作者:陶沅玱
* 给定一个二维数组,其每一行从左到右递增排序,从上到下也是递增排序。给定一个数,判断这个数是否在该二维数组中。
* Consider the following matrix:
* [
* [1, 4, 7, 11, 15],
* [2, 5, 8, 12, 19],
* [3, 6, 9, 16, 22],
* [10, 13, 14, 17, 24],
* [18, 21, 23, 26, 30]
* ]
* Given target = 5, return true.
* Given target = 20, return false.
*/
public class TwoArrayInFind {
/**
* 方法一
* @param array: 二维数组
* @param target: 要检索的数字
* @return
* 时间复杂度为O(n²), 空间复杂度为O(1)
*/
public boolean find(int[][] array, int target) {
if(array==null & array.length==0 & array[0].length==0) {
return false;
}
for(int i=0; i<array.length; i++) {
for(int j=0; j<array[0].length; j++) {
if(target == array[i][j]) {
return true;
}
}
}
return false;
}
/**
* 要求时间复杂度 O(M + N),空间复杂度 O(1)。其中 M 为行数,N 为 列数。
* 该二维数组中的一个数,小于它的数一定在其左边,大于它的数一定在其下边。
* 因此,从右上角开始查找,就可以根据 target 和当前元素的大小关系来缩小查找区间,
* 当前元素的查找区间为左下角的所有元素。
*/
public boolean find2(int[][] nums, int target){
if(nums==null & nums.length==0 & nums[0].length==0){
return false;
}
//从右上角开始查找, 因此定义变量获取二维数组的长度
int rows = nums.length;
int cols = nums[0].length;
//右上角的坐标(也表示target的坐标)
int a = 0;
int b = nums[0].length-1;
//每次都要从右上角开始遍历
//因此结束条件为:行超过>nums.length, 列小于0
while(a <= nums.length-1 && b>=0 ){
System.out.println(nums[a][b]);
//目标小于当前坐标值,往下走
if(nums[a][b] < target){
a++;
}
//目标大于当前坐标值,往左走
else if(nums[a][b] > target){
b--;
}
//否则,相同
else {
return true;
}
}
return false;
}
public static void main(String[] args) {
int[][] arr = new int[][] { { 1, 4, 7, 11, 15 }, { 2, 5, 8, 12, 19 }, { 3, 6, 9, 16, 22 },
{ 10, 13, 14, 17, 24 }, { 18, 21, 23, 26, 30 } };
System.out.println(new TwoArrayInFind().find2(arr, 18));
}
}
三、替换空格
/**
* 将一个字符串中的空格替换成 "%20"。
*/
public class ReplaceBlank {
//自己写的
//因为替换空格的有肯能不是一个字符,因此字符串还需要‘扩容’,因此此处必须定义成StringBuffer类型的数组
//a_b_c 此时_表示一个空格
public String replaceStr(StringBuffer str){
//使p1指向该字符串的最后一位下标
int p1 = str.length()-1;
//System.out.println("p1: " + p1);
//此处for循环中不可以使用 i<str.length(), 因为str一有空格就会加两个空格,因此此处必须用 i<p1
for(int i=0; i<p1; i++){
//判断如果有空格,那么再添加两个空格字符
if(str.charAt(i) == ' '){
//System.out.println("发现空格是第几位:"+ i);
str.append(" ");
}
}
//此时变成了 a_b_c____
//定义p2指向最新字符串的最后一位下标
int p2 = str.length()-1;
//解题思路:p1从最后一位往前一位,发现空格,把p1++所指向字符串的值给p2下标所指向字符串的值,
// 然后 setCharAt(--p2, 0), setCharAt(--p2, 2), setCharAt(--p2, %),
// 此时p2=p1,
//因为此时p2下标指向的字符是 '%', 因此p2需要向前一位,即p2--
//p1继续往前。。重复之前步骤
//直到p1=0, 循环结束
while(p1 >= 0) {
//System.out.println(p1);
if (str.charAt(p1) == ' ') {
str.setCharAt(p2--, '0');
str.setCharAt(p2--, '2');
str.setCharAt(p2, '%');
//此时p2=p1
//System.out.println(str.toString())
//因为此时p2下标指向的字符是 '%',因此p2需要向前一位,即p2--
p2--;
}
//如果当前p1指向的位不是空格,那么需要把当前p1指向的字符直接给p2,然后p2--
else{
char c = str.charAt(p1);
str.setCharAt(p2, c);
p2--;
}
p1--;
}
return str.toString();
}
//标准答案
//解题思路
//在字符串尾部填充任意字符,使得字符串的长度等于替换之后的长度。因为一个空格要替换成三个字符(%20),
// 因此当遍历到一个空格时,需要在尾部填充两个任意字符。
//令 P1 指向字符串原来的末尾位置,P2 指向字符串现在的末尾位置。
// P1 和 P2 从后向前遍历,当 P1 遍历到一个空格时,就需要令 P2 指向的位置依次填充 02%(注意是逆序的),
// 否则就填充上 P1 指向字符的值。
//从后向前遍是为了在改变 P2 所指向的内容时,不会影响到 P1 遍历原来字符串的内容。
public String replaceSpace(StringBuffer str) {
int P1 = str.length() - 1;
for (int i = 0; i <= P1; i++)
if (str.charAt(i) == ' ')
str.append(" ");
int P2 = str.length() - 1;
/**
* while循环参数详解
* p1>=0 证明遍历到头了
* p2>p1 每一次添加完'%20'后,p2=p1
*/
while (P1 >= 0) {
//此处是判断当前p1前面的那个字符是不是空格
//而我写的是判断当前p1这个字符是不是空格
char c = str.charAt(P1--);
if (c == ' ') {
str.setCharAt(P2--, '0');
str.setCharAt(P2--, '2');
str.setCharAt(P2--, '%');
} else {
str.setCharAt(P2--, c);
}
}
return str.toString();
}
public static void main(String[] args){
System.out.println(new ReplaceBlank().replaceStr(new StringBuffer("a b c")));
}
}