zoukankan      html  css  js  c++  java
  • 《算法》第一章部分程序 part 1

    ▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法

    ● 代码,二分搜索

     1 package package01;
     2 
     3 import java.util.Arrays;
     4 import edu.princeton.cs.algs4.StdRandom;
     5 
     6 public class class01
     7 {
     8     public int binarySearch(int [] a, int target)   // 非递归实现
     9     {
    10         int lp = 0, rp = a.length - 1;
    11         for(;lp <= rp;)                             // 含等号的条件,后面修改 lp 和 rp 是使用强的跳跃条件
    12         {
    13             int mp = lp + (rp - lp) / 2;
    14             if (target < a[mp])
    15                 rp = mp - 1;                        // 不要使用 mp 作为跳跃条件,会导致死循环
    16             else if (target > a[mp])
    17                 lp = mp + 1;
    18             else
    19                 return mp;
    20         }
    21         return -1;
    22     }
    23 
    24     public int binarySearchRecursion(int [] a, int target)// 递归实现
    25     {
    26         return binarySearchRecursionKernel(a,target,0,a.length-1);
    27     }
    28 
    29     private int binarySearchRecursionKernel(int [] a, int target, int lp, int rp)
    30     {
    31         for(;lp<=rp;)
    32         {
    33             int mp = lp + (rp - lp) / 2;
    34             if (target < a[mp])
    35                 return binarySearchRecursionKernel(a,target,lp,mp - 1);
    36             else if (target > a[mp])
    37                 return binarySearchRecursionKernel(a,target,mp + 1, rp);
    38             else
    39                 return mp;
    40         }
    41         return -1;
    42     }
    43 
    44     public static void main(String[] args)
    45     {
    46         int N = 10000;
    47         int [] a = new int [N];
    48         for(int i=0;i<N;i++)
    49             a[i] = i;//(int)(StdRandom.uniform()*10000);    // 注释部分留作随机检验
    50         //Arrays.sort(a);
    51 
    52         int target = 7919;//(int)(StdRandom.uniform()*10000);
    53         int output1 = binarySearch(a,target);
    54         int output2 = binarySearchRecursion(a,target);
    55 
    56         System.out.printf("
    %d,%d
    ",output1,output2);
    57         return;
    58     }
    59 }

    ● 重复元素二分搜索,包括查找第一次出现、最后一次出现,以及出现多少次

     1 package package01;
     2 
     3 import java.util.Arrays;
     4 import edu.princeton.cs.algs4.StdRandom;
     5 
     6 public class class01
     7 {
     8     public int binarySearchFirst(int [] a, int target)                        // 寻找第一个等于键值的目标
     9     {
    10         return binarySearchFirstKernel(a, target, 0, a.length-1);
    11     }
    12 
    13     private int binarySearchFirstKernel(int [] a, int target,int lp,int rp)    // 添加起点和终点(两端点都包含),为了能与 Count 函数配合
    14     {
    15         for(;lp<=rp;)
    16         {
    17             int mp = lp + (rp - lp) / 2;
    18             if (target < a[mp])
    19                 rp = mp - 1;
    20             else if (target > a[mp])
    21                 lp = mp + 1;
    22             else if(mp == 0 || target > a[mp-1])    // target == a[mp],找第一个
    23                 return mp;                          // a[mp] 就是第一个
    24             else                                    // a[mp] 前面还有等值的,不能强跳跃,否则可能跨空
    25                 rp = mp;
    26         }
    27         return -1;
    28     }
    29 
    30     public int binarySearchLast(int [] a, int target)                        // 寻找最后一个等于键值的目标
    31     {
    32         return binarySearchLastKernel(a,target, 0, a.length-1);
    33     }
    34 
    35     private int binarySearchLastKernel(int [] a, int target,int lp, int rp)    // 添加起点和终点(两端点都包含)
    36     {
    37         for(;lp<=rp;)
    38         {
    39             int mp = lp + (rp - lp) / 2;
    40             if (target < a[mp])
    41                 rp = mp - 1;
    42             else if (target > a[mp])
    43                 lp = mp + 1;
    44             else if(mp == a.length-1 || target < a[mp+1])   // target == a[mp],找最后一个
    45                 return mp;                                  // a[mp] 就是第一个
    46             else                                            // a[mp] 后面还有等值的,不能强跳跃,否则可能跨空
    47                 lp = mp;
    48         }
    49         return -1;
    50     }
    51 
    52     public int binarySearchCount(int [] a, int target)                        // 寻找等于键值的元素个数
    53     {
    54         int lp = 0, rp = a.length-1;
    55         for(;lp<=rp;)
    56         {
    57             int mp = lp + (rp - lp) / 2;
    58             if (target < a[mp])
    59                 rp = mp - 1;
    60             else if (target > a[mp])
    61                 lp = mp + 1;
    62             else                                            // 找到元素后,搜查首个和最后一个进行计数
    63                 return binarySearchLastKernel(a,target,lp,rp) - binarySearchFirstKernel(a,target,lp,rp) + 1;
    64         }
    65         return -1;
    66     }
    67 
    68     public static void main(String[] args)
    69     {
    70         int N = 10000;
    71         int [] a = new int [N];
    72         for(int i=0;i<N;i++)
    73             a[i] = i/100;//(int)(StdRandom.uniform()*10000);    // 用于随机测试
    74         //Arrays.sort(a);
    75 
    76         int target = 29;//(int)(StdRandom.uniform()*10000);        // 可以检验边界 0,99 等情况
    77         int output1 = binarySearchFirst(a,target);
    78         int output2 = binarySearchLast(a,target);
    79         int output3 = binarySearchCount(a,target);
    80 
    81         System.out.printf("
    %d,%d,%d
    ",output1,output2,output3);
    82         return;
    83     }
    84 }

     ● 数组随机化

     1 package package01;
     2 
     3 public class class01
     4 {
     5     public static void shuffle(Object[] a)
     6     {
     7         int n = a.length;
     8         for (int i = 0; i < n; i++)// 每次在 a[0] ~ a[i] 中随机挑一个 a[r],交换 a[i] 与a[r]
     9         {
    10             int r = (int)(Math.random() * (i + 1));
    11             Object swap = a[r];
    12             a[r] = a[i];
    13             a[i] = swap;
    14         }
    15     }
    16 
    17     public static void shuffle2(Object[] a)
    18     {
    19         int n = a.length;
    20         for (int i = 0; i < n; i++)// 每次在 a[i] 右边随机挑一个 a[r],交换 a[i] 与a[r]
    21         {
    22             int r = i + (int)(Math.random() * (n - i));
    23             Object swap = a[r];
    24             a[r] = a[i];
    25             a[i] = swap;
    26         }
    27     }
    28 
    29     public static void main(String[] args)
    30     {
    31         String[] a = { "0","1","2","3","4","5","6","7","8","9" };
    32         class01.shuffle(a);
    33         for (int i = 0; i < a.length; i++)
    34             System.out.print(a[i]);
    35 
    36         System.out.print("
    ");
    37 
    38         String[] b = { "0","1","2","3","4","5","6","7","8","9" };
    39         class01.shuffle2(b);
    40         for (int i = 0; i < a.length; i++)
    41             System.out.print(b[i]);
    42 
    43         return;
    44     }
    45 }

     ● 计算图连通分量的算法。输入文件第一行是节点数,后面每行是一个连接的两端节点编号,用 java class01 < inputFile.txt 来运行。

      1 package package01;
      2 
      3 import edu.princeton.cs.algs4.StdIn;
      4 import edu.princeton.cs.algs4.StdOut;
      5 
      6 public class class01
      7 {
      8     private int[] parent;   // 节点祖先标记
      9     private int[] rank;     // 树深度,仅根节点有效
     10     private int count;      // 节点数
     11 
     12     public class01(int n)
     13     {
     14         count = n;
     15         parent = new int[n];
     16         rank = new int[n];
     17         for (int i = 0; i < n; i++)
     18         {
     19             parent[i] = i;
     20             rank[i] = 1;    // 源代码用的是 0 
     21         }
     22     }
     23 
     24     public int find(int p)  // 寻找 p 的根标号
     25     {
     26         for (validate(p); p != parent[p]; p = parent[p]);
     27         return p;
     28     }
     29 
     30     public int count()  // 节点数
     31     {
     32         return count;
     33     }
     34 
     35     public boolean connected(int p, int q)  // 判断 p 与 q 是否连通
     36     {
     37         return find(p) == find(q);
     38     }
     39 
     40     public void union(int p, int q)         // 合并 p 和 q
     41     {
     42         int rootP = find(p);
     43         int rootQ = find(q);
     44         if (rootP == rootQ)
     45             return;
     46 
     47         if (rank[rootP] < rank[rootQ])      // 较小树连接到较大树的树根上,树高按最大值计算
     48             parent[rootP] = rootQ;
     49         else if (rank[rootP] > rank[rootQ])
     50             parent[rootQ] = rootP;
     51         else                                // 两树等大,合并后树高增一
     52         {
     53             parent[rootQ] = rootP;
     54             rank[rootP]++;
     55         }
     56         count--;                            // 合并后连接分量减少
     57     }
     58 
     59     public void union2(int p, int q)        // 合并 p 和 q,第二种方法,更快
     60     {
     61         int rootP = find(p);
     62         int rootQ = find(q);
     63         if (rootP == rootQ)
     64             return;
     65 
     66         if (rank[rootP] < rank[rootQ])
     67         {
     68             parent[rootP] = rootQ;
     69             rank[rootQ] += rank[rootP];     // 树高按加和计算
     70         }
     71         else
     72         {
     73             parent[rootQ] = rootP;
     74             rank[rootP] += rank[rootQ];
     75         }
     76         count--;
     77     }
     78 
     79     private void validate(int p)    // 判断输入的 p 是否合法
     80     {
     81         if (p < 0 || p >= parent.length)
     82             throw new IllegalArgumentException("
    p = " + p + "is illegal
    ");
     83     }
     84 
     85     public static void main(String[] args)
     86     {
     87         int n = StdIn.readInt();
     88         class01 uf = new class01(n);
     89         for (; !StdIn.isEmpty();)
     90         {
     91             int p = StdIn.readInt();
     92             int q = StdIn.readInt();
     93             if (uf.connected(p, q))
     94                 continue;
     95             uf.union(p, q);
     96             //StdOut.println(p + " " + q);
     97         }
     98         StdOut.println(uf.count() + " components");
     99     }
    100 }
  • 相关阅读:
    排列 POJ
    [kuangbin带你飞]专题二十一 概率&期望 部分题解
    队列最大值&滑动窗口最大值【剑指offer】
    Python实现可视化界面多线程豆瓣电影信息爬虫,并绘制统计图分析结果
    剑指offer【复杂链表的复制】
    树上博弈——从根节点先后走向叶子节点输赢【递归水题】
    给一个长度为n的字符串,找出长度为m的最小字典子序列【单调栈】
    Hrbust 1814 小乐乐的化妆品【01背包】
    Hrbust 1541集合划分 & Hrbust 2002幂集【dp】
    Hrbust 1333 GG的关心【01背包】
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9748440.html
Copyright © 2011-2022 走看看