前缀树 和 贪心算法经典题目

111 阅读1分钟

1.前缀树

public class Trie {
    Node root;
    public Trie(){
        root = new Node();
    }

    //向树种插入字符串
    public  void Insert(String str){
        if(str==null) return;
        root.pass++;
        Node node = root;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if(node.nexts[c - 'a']==null){
                node.nexts[c-'a'] = new Node();
            }
            node = node.nexts[c-'a'];
            node.pass++;
        }
        node.end++;
    }

    //查询字符串出现了几次
    public int search(String str){
        if(str==null) return 0;
        Node node = root;
        int index = 0;
        for (int i = 0; i < str.length(); i++) {
            index = str.charAt(i) - 'a';
            if(node.nexts[index]==null || node.nexts[index].pass==0){
                return 0;
            }
            node = node.nexts[index];
        }
        return node.end>0?node.end:0;
    }

    //查询以str作为前缀的字符串数量
    public int searchPre(String str){
        if(str==null) return root.pass;
        Node node = root;
        int index = 0;
        for (int i = 0; i < str.length(); i++) {
            index = str.charAt(i) - 'a';
            if(node.nexts[index]==null || node.nexts[index].pass==0){
                return 0;
            }
            node = node.nexts[index];
        }
        return node.pass;
    }

    //删除字符串
    public void delete(String str){
        if(str==null || search(str)==0) return;
        Node node = root;
        int index = 0;
        node.pass--;
        for (int i = 0; i < str.length(); i++) {
            index = str.charAt(i)-'a';
            if(--node.nexts[index].pass==0){
                node.nexts[index] = null;
                return;
            }
            node = node.nexts[index];
        }

        node.end--;
    }
}

2.贪心算法经典题目

    //给定一个数组,数组中每个元素为一个会议,会议中记录了开始时间和结束时间。给定一个整型上班开始时间。
    // 返回一天最多可以安排的会议数
    public class Meeting implements Comparator<Meeting> {
        int startTime;
        int endTime;

        @Override
        public int compare(Meeting o1, Meeting o2) {
            return o1.endTime - o2.endTime;
        }
    }

    public static int maxMeetingNum(Meeting[] meetings, int startTime) {
        //按照会议结束时间先后排序
        Arrays.sort(meetings);
        int res = 0;
        for (int i = 0; i < meetings.length; i++) {
            if (meetings[i].startTime >= startTime) {
                res++;
                startTime = meetings[i].endTime;
            }
        }
        return res;
    }

/*    分金条问题:给定数组nums代表最终金条要分成这个样子。给定整型length代表金条的长度。
     每次分割的代价为当前金条的长度,怎样分最后的代价最小,返回代价。*/

    public static int minCost(int[] nums, int length) {
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        for (int i = 0; i < nums.length; i++) {
            queue.add(nums[i]);
        }
        int sum = 0;
        int cur = 0;
        while ((!queue.isEmpty())) {
            cur = queue.poll() + queue.poll();
            sum += cur;
            queue.add(cur);
        }
        return sum;
    }


    /*投资问题:
    给定一个Program数组,每个Program里存放了c:成本和b:利润
    给定一个整型k代表最多可以做k个项目
    给定一个整型x代表本金,问怎样使所得利益最大,并返回
    * */
    public class Program {
        int c;
        int b;
    }

    public static int getMaxBenifits(Program[] programs, int x, int k) {
        //小根堆
        PriorityQueue<Program> queue1 = new PriorityQueue<>(new Comparator<Program>() {
            @Override
            public int compare(Program o1, Program o2) {
                return o1.c - o2.c;
            }
        });
        //大根堆
        PriorityQueue<Program> queue2 = new PriorityQueue<>(new Comparator<Program>() {
            @Override
            public int compare(Program o1, Program o2) {
                return o2.b - o1.b;
            }
        });
        //将所有项目全部加入到小根堆里
        for (int i = 0; i < programs.length; i++) {
            queue1.add(programs[i]);
        }
        //当前可以做的起的项目按照利润全部放入大根堆
        while (!queue1.isEmpty()) {
            while (queue1.peek().c <= x) {
                queue2.add(queue1.poll());
            }
            //没有能够做的起的项目了,直接返回
            if(queue2.isEmpty()){
               return x;
            }
            //弹出能做的起的项目中利润最大的,更新x
            Program cur = queue2.poll();
            //进行k轮后结束
            if(--k<0) break;
            x = x+cur.b;

        }

        return x;
    }



    /*给定一个数组int[] nums,要求能随时返回其中位数
    * */
    public static int getMedian(int[] nums){
        //大根堆
        PriorityQueue<Integer> queue1 = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        //小根堆
        PriorityQueue<Integer> queue2 = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
        queue1.add(nums[0]);
        for (int i = 1; i < nums.length; i++) {
            //当前元素值
            int cur = nums[i];
            //当前值比大根堆顶部值小,加入小根堆
            if(cur<queue1.peek()){
                queue2.add(cur);
                //加入小根堆后判断是否小根堆长度超过大根堆长度2个,如果是弹出小根堆堆顶加入大根堆
                if(queue2.size()-queue1.size()>=2){
                    queue1.add(queue2.poll());
                }
            }
            //当前元素比大顶堆顶部值大或者相等,加入大根堆
            else {
                queue1.add(cur);
                //加入大根堆后判断大根堆长度是否超过小根堆长度2个,如果是将大根堆堆顶加入小根堆
                if(queue1.size()-queue2.size()>=2){
                    queue2.add(queue1.poll());
                }
            }
        }
        //两个堆长度不一样,返回较长的那个的顶部
        if(queue1.size()!=queue2.size()){
            return queue1.size()>queue2.size()?queue1.peek():queue2.peek();
        }
        //两个堆长度相同,返回两个堆顶部和的平均值
        return (queue1.peek()+queue2.peek())/2;
    }