一 : 数组中出现次数超过数组一半的数字
1.题目
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组
{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0 .
2.解题
2.1思路分析
思路一:定义map,使用<数字,次数>的映射关系,最后统计每个字符出现的次数 .
思路二:排序,出现次数最多的数字,一定在中间位置。然后检测中间出现的数字出现的次数是否符合要求 .
思路三:目标条件:目标数据超过数组长度的一半,那么对数组,我们同时去掉两个不同的数字,到最后剩下的一个数就是该数字。如果剩下两个,那么这两个也是一样的,就是结果),在其基础上把最后剩下的一个数字或者两个回到原来数组中,将数组遍历一遍统计一下数字出现次数进行最终判断 .
2.2具体代码
思路一代码 :
import java.util.*;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
int half = array.length/2;
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < array.length; i++) {
if(map.containsKey(array[i])){
int val = map.get(array[i]);
map.put(array[i],val+1);
if(map.get(array[i]) > half){
return array[i];
}
} else {
map.put(array[i],1);
if(map.get(array[i]) > half){
return array[i];
}
}
}
return 0;
}
}
思路二代码 :
import java.util.Arrays;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
int count = 0;
Arrays.sort(array);
int half = array[array.length/2];
for (int i = 0; i < array.length; i++) {
if(half == array[i]){
count++;
}
}
if(count > array.length/2){
return half;
} else {
return 0;
}
}
}
思路三代码 :
public class Test9 {
public int MoreThanHalfNum_Solution(int [] array) {
if(array == null){
return 0;
}
int target = array[0];
int times = 1;
for(int i = 1; i < array.length; i++){
if(times == 0){
target = array[i];
times = 1;
}
else if(array[i] == target){
times++;
}
else{
times--;
}
}
times = 0;
for(int i = 0; i < array.length; i++){
if(target == array[i]){
times++;
}
}
return times > array.length/2 ? target : 0;
}
}
二 : MP3光标位置
1.题目
MP3 Player因为屏幕较小,显示歌曲列表的时候每屏只能显示几首歌曲,用户要通过上下键才能浏览所有的歌曲。为了简化处理,假设每屏只能显示4首歌曲,光标初始的位置为第1首歌。
现在要实现通过上下键控制光标移动来浏览歌曲列表,控制逻辑如下:
歌曲总数<=4的时候,不需要翻页,只是挪动光标位置。
光标在第一首歌曲上时,按Up键光标挪到最后一首歌曲;光标在最后一首歌曲时,按Down键光标挪到第一首歌曲。
2. 歌曲总数大于4的时候(以一共有10首歌为例):
特殊翻页:屏幕显示的是第一页(即显示第1 – 4首)时,光标在第一首歌曲上,用户按Up键后,屏幕要显示最后一页(即显示第7-10首歌),同时光标放到最后一首歌上。同样的,屏幕显示最后一页时,光标在最后一首歌曲上,用户按Down键,屏幕要显示第一页,光标挪到第一首歌上。
一般翻页:屏幕显示的不是第一页时,光标在当前屏幕显示的第一首歌曲时,用户按Up键后,屏幕从当前歌曲的上一首开始显示,光标也挪到上一首歌曲。光标当前屏幕的最后一首歌时的Down键处理也类似。
其他情况,不用翻页,只是挪动光标就行。
2.解题
2.1 思路分析
首先 , 分为两种情况 , 歌曲数量小于等于4和歌曲数量大于4 .
当歌曲数量<=4时 , 只需控制光标移动 , 无需控制页数 ;
当歌曲数量>4时 , 对于特殊翻页和普通翻页 , 进行分别考虑 .
本题的难点 , 在于使用first控制页码 !!!
2.2具体代码
import java.io.FileReader;
import java.sql.SQLOutput;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int num = sc.nextInt();
String str = sc.next();
int first = 1;//控制页数
int index = 1; //控制光标位置
if (num <= 4) {
for (int j = 0; j < str.length(); j++) {
if (str.charAt(j) == 'U' && index == 1) {
index = num;
} else if (str.charAt(j) == 'D' && index == num) {
index = 1;
} else if (str.charAt(j) == 'U') {
index--;
} else if (str.charAt(j) == 'D') {
index++;
}
}
//此时就打印
for (int i = 1; i < num; i++) {
System.out.print(i + " ");
}
System.out.println(num);
System.out.println(index);
} else {
for (int j = 0; j < str.length(); j++) {
if (first == 1 && index == 1 && str.charAt(j) == 'U') {
first = num - 3;
index = num;
} else if (first == num - 3 && index == num && str.charAt(j) == 'D') {
first = 1;
index = 1;
} else if (first != 1 && index == first && str.charAt(j) == 'U') {
first--;
index--;
} else if (first != num - 3 && index == first + 3 && str.charAt(j) == 'D') {
first++;
index++;
} else if (str.charAt(j) == 'U') {
index--;
} else if (str.charAt(j) == 'D') {
index++;
}
}
//此时就打印
for (int i = first; i < first + 3; i++) {
System.out.print(i + " ");
}
System.out.println(first + 3);
System.out.println(index);
}
}
}
}
三 : mkdir
1.题目
工作中,每当要部署一台新机器的时候,就意味着有一堆目录需要创建。例如要创建目录“/usr/local/bin”,就需要此次创建“/usr”、“/usr/local”以及“/usr/local/bin”。好在,Linux下mkdir提供了强大的“-p”选项,只要一条命令“mkdir -p /usr/local/bin”就能自动创建需要的上级目录。
现在给你一些需要创建的文件夹目录,请你帮忙生成相应的“mkdir -p”命令。
2.题解
2.1 思路分析
需要分析两种情况 , 其中第二种我分析时没有考虑全面 :
- 后一个符号串和前一个符号串相等 , 此时只需保留后一个符号串 ;
- 后一个符号串包含前一个符号串 , 且后一个符号串的下一个位置需要是’/’ 例如 :
其次 , 在输出时 , 最后一个字符串打印完 , 还要再加一个换行符 , 否则会导致格式错误 .
2.2 代码实现
实现一 : 新建一个数组 , 用于存放最后要打印的目录 .
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
// 3
// /a
// /a/b
// /a/b/c
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int num = sc.nextInt();
String[] arr = new String[num];
String[] arr1 = new String[num];
for (int i = 0; i < num; i++) {
arr[i] = sc.next();
}
Arrays.sort(arr);
int j = 0;
int i = 0;
for (; i < num-1; i++) {
if((arr[i] == arr[i+1]) || (arr[i+1].contains(arr[i]) && arr[i+1].charAt(arr[i].length()) == '/')){
} else {
arr1[j++] = arr[i];
}
}
arr1[j] = arr[i];
for (String s : arr1) {
if(s != null) {
System.out.println("mkdir -p " + s);
} else {
break;
}
}
System.out.println();
}
}
}
实现二 : 不新建数组 , 而是使用伪删除法 , 创建boolean数组 , 表示原数组当中的某个目录是否已经被删除 .
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
// 接收n条路径
String[] path = new String[n];
for(int i = 0; i < n; ++i){
path[i] = sc.next();
}
// 对path中的n条路径进行排序
Arrays.sort(path);
// 将数组中:相等的元素以及前一个是后一个子串的字符串剔除掉
// 注意:此处采用标记法删除
boolean[] flag = new boolean[n];
for(int i = 0; i < path.length-1; ++i){
if(path[i].equals(path[i+1]) || // 两个字符串相等
path[i+1].contains(path[i]) &&
path[i+1].charAt(path[i].length()) == '/'){
flag[i] = true;
}
}
// 输出
for(int i = 0; i < n; ++i){
if(!flag[i]){
System.out.println("mkdir -p " + path[i]);
}
}
System.out.println();
}
}
}