zoukankan      html  css  js  c++  java
  • 算法刷题细节点总结

    1. 关于集合

    (1) 关于map

     遍历maphttps://www.cnblogs.com/imzhj/p/5981665.html

     感觉最好记的方法是这个:

    Map<String, String> map = new HashMap<String, String>();
    for (Entry<String, String> entry : map.entrySet()) {
        entry.getKey();
        entry.getValue();
    }

    关于get方法的一个注意点:

    if (!map.containsKey(keyStr)) map.put(keyStr, new ArrayList<String>());
     map.get(keyStr).add(s);  // map的get返回的不是一个副本,而是引用,所以直接修改就好,不需要修改后再put。对于基本类型是不可以这么做的

    (2) set集合的增删改元素方法和List集合是一样的吗?remove方法的一个疑问

     一样的,都是 add 和 remove 方法,只不过list的remove方法能按照index来删,而set只能按照Object来删。这里有一个长久以来的疑问是如果List集合中放入的是int型元素的话,如果此时使用remove方法,传入int的 话是按照索引来删除元素还是按照int的值来删除元素的呢?

    测试结果是还是按照索引来删,如果使用 (Integer)3 这种方式将int包装为Integer的话就会按照值去删。

    (3) set和list集合怎么和数组互转?

    参考: https://blog.csdn.net/my_precious/article/details/53010232

    (4) 关于PriorityQueue的用法

    首先要明白的是这个数据结构的特点,这个数据结构使得我们在往队列中加入元素时,虽然是乱序加入,但是队列中始终能够以某种优先级排列队列中的元素。 要注意一点的是

    并非像TreeMap一样完全有序,但是如果按照指定方式出队,结果可以是有序的。意思是不能保证队列是有序的,但是可以保证每次出队列出的是最小或最大的元素,这样以此出队才能保证有序

    此队列的 是按指定排序方式确定的最小 元素。如果多个元素都是最小值,则头是其中一个元素——选择方法是任意的。队列获取操作 pollremovepeek 和 element访问处于队列头的元素。

    注意,此实现不是同步的。如果多个线程中的任意线程修改了队列,则这些线程不应同时访问 PriorityQueue 实例。相反,请使用线程安全的 PriorityBlockingQueue 类。

    实现注意事项:此实现为排队和出队方法(offerpollremove() 和 add)提供 O(log(n)) 时间;为 remove(Object) 和 contains(Object) 方法提供线性时间;为获取方法(peekelement 和 size)提供固定时间。

    代码示例

    public class PriorityQueueTest {
        public static void main(String[] args) {
                    
            final PriorityQueue<Student> queue=new PriorityQueue<>();
    
            Student p1=new Student(95,"张三");
            Student p2=new Student(89,"李四");
            Student p3=new Student(89,"李四");
            Student p4=new Student(67,"王五");
            Student p5=new Student(92,"赵六");
            queue.add(p1);
            queue.add(p2);
            queue.add(p3);//add 和offer效果一样。
            queue.offer(p4);//add 方法实现,其实就是调用了offer
            queue.offer(p5)
    
            for (Student Student : queue) {
                System.out.println(Student.toString());
            }
            
            System.out.println("---------------------");
            while(!queue.isEmpty()){
                System.out.println(queue.poll());
            }       
        }
    
    }
    class Student implements Comparable{
        private int score;
        private String name;
        
        public Student(int age,String name){
            this.score=age;
            this.name=name;
        }
        public int getScore() {
            return score;
        }
        public void setScore(int score) {
            this.score = score;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String toString(){
            return "姓名:"+name+"-"+score+"分";
        }
    
        @Override
        public int compareTo(Object o) {
            Student current=(Student)o;
            if(current.getScore()>this.score){
                return 1;
            }else if(current.getScore()==this.score){
                return 0;
            }
            return -1;
        }
    }

    运行结果

    姓名:张三-95分
    姓名:赵六-92分
    姓名:王五-67分
    姓名:李四-89分
    ---------按顺序出队选座位------------
    姓名:张三-95分
    姓名:赵六-92分
    姓名:李四-89分
    姓名:李四-89分
    姓名:王五-67分

    逻辑上使用堆结构(完全二叉树)实现,物理上使用动态数组实现。 参考:https://blog.csdn.net/qq_35326718/article/details/72866180  https://blog.csdn.net/u013309870/article/details/71189189

    (5) 比较器

            Queue<Integer> pq=new PriorityQueue<Integer>(new Comparator<Integer>(){
                public int compare(Integer a, Integer b){   // 这里要严格写成和上面的一样
                    return b-a;
                }
            });

    原来上面的compare方法中参数类型写成了 int, 以为也能编译通过,结果不行,要严格和Comparator中的泛型一致。自定义了比较器后就可以在Collections和Arrays的sort方法对容器中的元素进行排序,默认是升序排序的。

    另两种比较器的使用形式:

    public class LeetCode{
      public static void main(String[] args){
        List<MeetingTime> list=new ArrayList<>();
        MeetingTime m1=new MeetingTime(10,30);
        MeetingTime m2=new MeetingTime(5,10);
        list.add(m1);
        list.add(m2);
        Collections.sort(list);
      }
    }
    
    // 让一个类实现Compable接口,然后在集合中就可以直接比较这个元素了,也就是定义类的时候自带比较器
    class MeetingTime implements Comparable<MeetingTime>{
      int startTime;
      int endTime;
    
      public void MettingTime(int startTime, int endTime){
        this.startTime=startTime;
        this.endTime=endTime;
      }
    
      @Override
      public int compareTo(MeetingTime m){
        return this.startTime-m.startTime;
      }
    }
    public class LeetCode{
      public static void main(String[] args){
        List<MeetingTime> list=new ArrayList<>();
        MeetingTime m1=new MeetingTime(10,30);
        MeetingTime m2=new MeetingTime(5,10);
        list.add(m1);
        list.add(m2);
        Collections.sort(list, new MyComparator());
      }
    
      // 单独定义一个实现Comparator接口的类,即单独弄一个通用的比较器,避免内部类不能复用的问题
      static class MyComparator implements Comparator<MeetingTime>{
        @Override
        public int compare(MeetingTime t1, MeetingTime t2){
          return t1.startTime-t2.startTime;
        }
      }
    }
    
    class MeetingTime {
      int startTime;
      int endTime;
    
      // 默认的构造函数是没有返回值的
      public MeetingTime(int startTime, int endTime) {
        this.startTime = startTime;
        this.endTime = endTime;
      }
    }

    上面用到了静态内部类的形式,这里复习下java静态类和非静态类的区别:https://www.cnblogs.com/muffe/p/6580208.html

    (6) List在指定位置插入

    void  add(int index, E element);

    2. 关于字符和字符串,不同类型的数字

    String判断相等要用equals方法,不能直接用等号。

    利用trim()方法可以快速去除字符串的前导空白和尾部空白

    (1) 相互转换

     int转String直接加""即可,String转int需要用到Integer.parseInt()方法。

     String转char数组直接调用toCharArray()方法,

     String与char互转,例如将“49”转化成‘49’

     char与int互转。

    package CodeTest;
    
    public class LeetCode {
    
      // int, char, String互转测试
      public static void main(String[] args) {
        int int49 = 49;
        int int4 = 4;
    
        /*-------int和char互转----------*/
        // char c = '49';  错误,应该是字符串
        char char49 = (char) int49;  //int -->char
        System.out.println((char) char49);   // 结果是1,因为49应该转为String,而不是char
        //System.out.println((String)char49); 错误,不可以这么用
    
        char char4;
        char4 = (char) int4;
        System.out.println(char4); //int -->char, 乱码,没有转成功
    
        char4 = (char) (int4 + 48);
        System.out.println(char4); //成功输出4,上面要加强转,否则编译不通过
    
        int4 = char4 - '0';
        System.out.println(int4); //char -->int, 直接减去字符0就可以了
    
        /*-------int和String互转----------*/
        System.out.println(String.valueOf(4));
        System.out.println(Integer.parseInt("4"));
    
        /*-------String和char互转----------*/
        char[] crs = "test".toCharArray();
        String str = String.valueOf(crs);
    
        char chr = '4';
        str = String.valueOf(chr);  // char -->String
        System.out.println(str);
    
        // str="4"; 对于单个字符的String --> char 好像还是只能用toCharArray
      }
    }

    (2) 快速逆转字符串

     String reversed = new StringBuilder(s).reverse().toString()

    (3) split和replaceAll按多个字符串匹配

         // 这里用“|”来匹配多个替换,对于中括号,前面要加上转义字符 \
            String str=input.replaceAll(",| |\]|\[","");

    (4) double, long, int

    做算法题时遇到一个比较尴尬的问题,用到Math.pow()这个函数求指数的时候,因为它返回的是double,结果之前的变量用的是int或long,结果编译阶段各种出错,现在来总结下遇到的转换方式

    int mod = (int)Math.pow(10, 9) + 7
    // long res; int mod
    return (int) (res % mod);    // 正确
    return (int) res % mod;    // 错误,编译不通过

    3. DFS&BFS&DP

    BFS和DFS遍历时不要忘记加visited数组来标记已经访问过的数组,否则会重复遍历。

    关于dp的一个心得:dp分为自顶向下和自低向上,其实两者都是从末端的临界开始往另一侧考虑,通俗的说就是从最边上的条件变化入手。

    BFS如何出完一层之后,再出下一层?

    4. 其它

    一些有用的参考代码片断:

     nusm[0]=nums[n++]=1;  // 可以这么赋值但不可以这么定义
    //return new int[2]{i+1,j+1}; 错误,编译不通过不能在此处加2
    return new int[]{i+1,j+1};
    for(int[] row:dp) Arrays.fill(row, Integer.MIN_VALUE);
            int[][] mp = new int[m][26];
            Map<String, Integer> dp = new HashMap<>();
            for (int i = 0; i < m; i++) 
                for (char c:stickers[i].toCharArray()) mp[i][c-'a']++
                for (int j = 0; j < 26; j++) {
                    if (tar[j] > 0 ) 
                        for (int k = 0; k < Math.max(0, tar[j]-mp[i][j]); k++)
                            sb.append((char)('a'+j));
                }
  • 相关阅读:
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1131 Subway Map (30 分)
    PAT 甲级 1131 Subway Map (30 分)
    AcWing 906. 区间分组 区间贪心
    AcWing 907. 区间覆盖 区间贪心
  • 原文地址:https://www.cnblogs.com/f91og/p/9629645.html
Copyright © 2011-2022 走看看