• 提前批笔试一道算法题的Java实现


    题目描述

    这是2021广联达校招提前批笔试算法题之一。
    我们希望一个序列中的元素是各不相同的,但是理想和显示往往是有差距的。现在给出一个序列A,其中难免有相同的元素,现在提供了一种变化方式,使得经过若干次操作后一定可以得到一个元素各不相同的序列。
    这个操作是这样的,令x为序列中最小的重复数字,你需要删除序列左数第一个x,并把第二个x替换为2*x。请你输出最终的序列。
    例如原序列是[2,2,1,1,1],一次变换后变为[2,2,2,1],两次变换后变为[4,2,1],变换结束。

    输入描述

    输入第一行包含一个正整数n,表示序列的长度为n。(1<=n<=50000)
    第二行有n个整数,初始序列中的元素。(1<=a_i<=10^8)

    输出描述

    输出包含若干个整数,即最终变换之后的结果。

    算法思路

    通过HashSet和HashMap实现重复元素存入集合以及元素出现次数的统计;
    递归思想。

    算法实现

    import java.util.*;
    
    /**
     * @author Chiaki
     */
    public class Main {
        public static void main(String[] args) {
            int n = 6;
            int[] arr = {1,1,2,2,4,4};
            long s = System.currentTimeMillis();
            int[] res = getArray(n, arr);
            long e = System.currentTimeMillis();
            System.out.println("耗时:" + (e - s) + "ms");
            System.out.print("[");
            for (int i = 0; i < res.length; i++) {
                if (i < res.length - 1) {
                    System.out.print(res[i] + ",");
                } else {
                    System.out.print(res[i] + "]");
                }
            }
            System.out.println();
        }
    
        /**
         * 按规则处理数组并返回新的无重复元素的数组
         * @param n 数组长度
         * @param arr 初始数组
         * @return 无重复元素的数组
         */
        public static int[] getArray(int n, int[] arr) {
            // 递归停止条件:只有一个元素直接返回无需进行后续操作
            if (n == 1) {
                return arr;
            }
            List<Integer> list = new LinkedList<>();
            Set<Integer> set = new HashSet<>();
            Map<Integer,Integer> map = new HashMap<>(n);
            // 遍历数组
            for (int i : arr) {
                // 数组值放入链表方便操作
                list.add(i);
                // 利用HashSet判断元素重复
                // 并统计元素出现次数放入HashMap
                if (!set.add(i)) {
                    int count = map.get(i);
                    count++;
                    map.put(i, count);
                    continue;
                }
                map.put(i, 1);
            }
            // 递归停止条件:HashSet元素个数与数组长度相同
            if (set.size() == n) {
                return arr;
            }
            // 将HashSet清空用来存放重复的元素
            set.clear();
            for (Integer i : map.keySet()) {
                if (map.get(i) > 1) {
                    set.add(i);
                }
            }
            // 按规则去重 迭代停止条件:HashSet为空
            while (!set.isEmpty()) {
                // 从最小的重复元素开始
                int minValue = Collections.min(set);
                // 定义计数器
                int count = 1;
                // 遍历链表
                for (int i = 0; i < list.size(); i++) {
                    // 碰到重复元素的第一个时赋值为0 计数器自增
                    if (list.get(i).equals(minValue) && count == 1) {
                        list.set(i, 0);
                        count++;
                    }
                    // 碰到重复元素的第二个时按要求赋值 计数器自增
                    if (list.get(i).equals(minValue) && count == 2) {
                        list.set(i, 2 * list.get(i));
                        count++;
                    }
                }
                // 操作结束后移除HashSet的当前重复元素并继续迭代
                set.remove(minValue);
            }
            // 将链表中赋值为0的元素删除
            list.removeIf(s -> s.equals(0));
            // 剩下的元素存放到数组作为结果
            int[] res = new int[list.size()];
            for (int i = 0; i < res.length; i++) {
                res[i] = list.get(i);
            }
            // 另外一种简单写法
            /*int[] res = list.stream().mapToInt(Integer::valueOf).toArray();*/
            // 递归调用
            return getArray(res.length, res);
        }
    }
    

    运行结果

    耗时:33ms
    [2,8,4]

  • 相关阅读:
    Flutter 容器(4)
    Linux 安装maven环境
    ajaxStart、ajaxStop使用注意事项
    jquery里用正则来验证密码,必须包含大小写字母,数字及特殊符号,或最少包含两种
    Nginx 相关介绍(Nginx是什么?能干嘛?配有图片示例)
    常见web攻击总结
    用php的chr和ord函数实现字符串和ASCII码互转
    消息队列设计精要
    mysql索引总结----mysql 索引类型以及创建
    MySQL事务隔离级别详解
  • 原文地址:https://www.cnblogs.com/chiaki/p/13401195.html
Copyright © 2020-2023  润新知