算法---数组

一 : 数组中出现次数超过数组一半的数字

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 思路分析

需要分析两种情况 , 其中第二种我分析时没有考虑全面 :

  1. 后一个符号串和前一个符号串相等 , 此时只需保留后一个符号串 ;
  2. 后一个符号串包含前一个符号串 , 且后一个符号串的下一个位置需要是’/’ 例如 :

在这里插入图片描述

其次 , 在输出时 , 最后一个字符串打印完 , 还要再加一个换行符 , 否则会导致格式错误 .

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();
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值