• 算法刷题细节点总结


    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));
                }
  • 相关阅读:
    [LeetCode]Subsets II
    [LeetCode]Subsets
    [LeetCode]Combinations
    [LeetCode]Minimum Window Substring
    [LeetCode]Search a 2D Matrix
    [LeetCode]Edit Distance
    [LeetCode]Simplify Path
    Adaboost算法
    [LeetCode]Text Justification
    31、剑指offer--从1到n整数中1出现次数
  • 原文地址:https://www.cnblogs.com/f91og/p/9629645.html
Copyright © 2020-2023  润新知