目录
一、数组中重复的数字
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是2或者3。存在不合法的输入的话输出-1。
示例:
输入: [2,3,1,0,2,5,3]
返回值: 2
说明: 2或3都是对的
数据范围:0 ≤ n ≤ 10000
解题思路一:
不断交换数组下标和元素,使得元素的值与下标相等。交换的过程中,如果发现已有元素的值和下标相等,则将该重复的元素返回。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param numbers int整型一维数组
* @return int整型
*/
public int duplicate (int[] numbers) {
if (numbers == null || numbers.length == 0) {
return -1;
}
for (int i = 0; i < numbers.length; ++i) {
while (i != numbers[i]) {
if (numbers[i] == numbers[numbers[i]]) {
return numbers[i];
}
int temp = numbers[i];
numbers[i] = numbers[temp];
numbers[temp] = temp;
}
}
return -1;
}
}
时间复杂度o(n),空间复杂度o(1)
解题思路二:创建一个哈希表,依次遍历元素,如果该元素不存在表中,将该元素加入;如果存在,则将该元素返回。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param numbers int整型一维数组
* @return int整型
*/
public int duplicate (int[] numbers) {
HashSet<Integer> hashset = new HashSet<>();
for(int i : numbers){
if(hashset.contains(i)){
return i;
}
hashset.add(i);
}
return -1;
}
}
时间复杂度o(n),空间复杂度o(n)
二、寻找目标值 —— 二维数组
在一个n*md的二维数组 plants
记录了园林景观的植物排布情况,具有以下特性:
- 每行中,每棵植物的右侧相邻植物不矮于该植物;
- 每列中,每棵植物的下侧相邻植物不矮于该植物。
请判断 plants
中是否存在目标高度值 target
。
示例
输入:plants = [[2,3,6,8],[4,5,8,9],[5,9,10,12]], target = 8 输出:true
输入:plants = [[1,3,5],[2,5,7]], target = 4 输出:false
数据范围: 0 <= n <= 1000 0 <= m <= 1000
解题思路一:
如果将二维数组元素的值类比成我们可以看得见的颜色,数值越大颜色越深。
我们可以得出:当元素位于二维数组越靠左上的位置,值越小;越靠右下的位置值越大。
以左下角的元素为坐标原点,建立一个二维直角坐标系,列用col表示,行用row表示。
从左下角开始遍历整个数组,如果一个数比左下角元素小,col+1;比左下角元素大,row+1。
class Solution {
public boolean findTargetIn2DPlants(int[][] plants, int target) {
if(plants == null || plants.length == 0 || plants[0].length ==0){
return false;
}
int rows = plants.length; //总共的行数
int cols = plants[0].length; //总共的列数
//以左下角为起点遍历二维数组
int row = rows -1;
int col = 0;
while(row >=0 && col <= cols-1 ){
if(target > plants[row][col]){
col++;
}else if(target < plants[row][col]){
row--;
}else{
return true;
}
}
return false;
}
}
时间复杂度o(n+m),空间复杂度o(1)
解题思路二:
本题没有确保每行的第一个整数大于前一行的最后一个整数,因此我们无法采取两次二分的做法。
只能遍历行或列,然后再对列或行进行二分查找。
class Solution {
public boolean findTargetIn2DPlants(int[][] plants, int target) {
if(plants == null || plants.length == 0 || plants[0].length ==0){
return false;
}
int rows = plants.length; //总共的行数
int cols = plants[0].length; //总共的列数
for(int i = 0; i < rows; ++i){ //遍历行
int low = 0,high = cols -1;
while(low <= high ){ //对列进行二分查找
int mid = (low+high) >> 1;
if(plants[i][mid] > target){
high = mid -1;
}else if(plants[i][mid] < target){
low = mid +1;
}else{
return true;
}
}
}
return false;
}
}
时间复杂度:O(mlogn) 或 O(nlogm),空间复杂度:O(1)
三、替换空格
解题思路一:
利用StringBuilder的append方法,当遇到空格时,向其添加“%20”;当遇到非空格时,向其添加该元素,最后再转化成字符串类型。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param s string字符串
* @return string字符串
*/
public String replaceSpace (String s) {
StringBuilder sd = new StringBuilder();
for(int i = 0; i < s.length(); ++i){
if(s.charAt(i) == ' '){
sd.append("%20");
}else{
sd.append(s.charAt(i));
}
}
return sd.toString();
}
}
时间复杂度o(n),空间复杂度o(n)
解题思路二:
一个空格占用一个空间,%20占用三个空间。所以替换后的字符串长度 = 原来的字符串长度 + 空格个数 *2 。由于Java中不能实现自动扩容,所以需要新建一个字符数组(C++不用),遍历原来的字符串,当遇到空格时,向其添加“%20”;当遇到非空格时,向其添加该元素,最后再转化成字符串类型。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param s string字符串
* @return string字符串
*/
public String replaceSpace (String s) {
int count = 0; //用来记录空格个数
for(int i = 0;i < s.length(); ++i){
if(s.charAt(i) == ' ')
count++;
}
char res[] = new char[s.length()+ count *2];
int k = 0;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) == ' '){
res[k++] = '%';
res[k++] = '2';
res[k++] = '0';
}else{
res[k++] = s.charAt(i);
}
}
return new String(res);
}
}
时间复杂度o(n),空间复杂度o(n)
四、从尾到头打印链表
解题思路一:
创建一个ArrayList,,每一次都向ArrayList的起始处增添元素。
import java.util.*;
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if(listNode == null){
return new ArrayList<>();
}
ArrayList<Integer> list = new ArrayList<>();
while(listNode != null){
list.add(0,listNode.val); //将listNode.val的值添加到list的开头
listNode = listNode.next;
}
return list;
}
}
时间复杂度o(n),空间复杂度o(n)
解题思路二:
利用栈后进先出的特性,创建一个栈,先把遍历结果存入栈中,最后再弹出栈中元素。
import java.util.*;
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> list = new ArrayList<>();
Stack<Integer> stack = new Stack<>();
while(listNode != null){
stack.push(listNode.val);
listNode = listNode.next;
}
while(!stack.empty()){
list.add(stack.pop());
}
return list;
}
}
时间复杂度o(n),空间复杂度o(n)
感谢您的观看,希望你今天特别特别开心,加油~