数据结构题目训练记录(Java书写) One

此篇笔记,涉及到 数据结构中 序列,链表的使用

 

一、最大子列和问题

给定K个整数组成的序列{ N1​​, N2​​, ..., NK​​ },“连续子列”被定义为{ Ni​​, Ni+1​​, ..., Nj​​ },其中 1。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。

本题旨在测试各种不同的算法在各种数据情况下的表现。各组测试数据特点如下:

  • 数据1:与样例等价,测试基本正确性;
  • 数据2:102个随机整数;
  • 数据3:103个随机整数;
  • 数据4:104个随机整数;
  • 数据5:105个随机整数;

输入格式:

输入第1行给出正整数K (≤);第2行给出K个整数,其间以空格分隔。

输出格式:

在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。

输入样例:

6
-2 11 -4 13 -5 -2
 

输出样例:

20

第一种方法:三重循环法,时间复杂度为 O(n3)

 1 /**
 2  *  这里用的第一种方法是三重循环方法 时间复杂度为 O(n^3)
 3  *  法一:三重循环。第一重标记子列最左端,第二重标记子列最右端,第三重由子列左端累加到子列右端。
 4  */
 5 public class MaxSum1{
 6     public static int MaxSum1s(int A[])
 7     {
 8         int ThisSum = 0, MaxSum = 0;
 9         int i, j ,k;
10         for(i = 0; i < A.length; i++)  // i 是子列最左端
11         {
12             for(j = i; j < A.length; j++)  
13             {
14                 ThisSum = 0;  // 每次都要将 ThisSum 归零,累加新一轮的子列和
15                 for (k = i; k < j; k++)  // 将 A[i] 到 A[j] 累加,得到子列和
16                     ThisSum += A[k];
17                 if(ThisSum > MaxSum)  // 如果这一轮的子列和比最大子列和还大,存入 MaxSum
18                     MaxSum = ThisSum;
19             }
20         }
21         return MaxSum;
22     }
23 
24     public static void main(String[] args)
25     {
26         int  lists[] = new int[] {-2 ,11, -4, 13, -5, -2};
27         System.out.println(MaxSum1s(lists));
28     }   
29 }

第二种方法:二重循环法

 1 /**
 2  *  法二:二重循环。对于相同的子列左端位置 i ,不同的右端位置 j ,我们只要每次在右端累加一项,即可求得每一个子列和。
 3  */
 4 public class MaxSum2{
 5     public static int MaxSums(int [] A)
 6     {
 7         int MaxSum = 0, ThisSum = 0;
 8         int i, j;
 9         for(i = 0; i < A.length; i++)
10         {
11             ThisSum = 0;
12             for(j = i; j < A.length; j++)
13             {
14                 ThisSum += A[j];
15                 if (ThisSum > MaxSum)  // 这里改成了,从 i 到 任意一处 j 来进行比较
16                 {
17                     MaxSum = ThisSum;
18                 }
19             }
20         }
21         return MaxSum;
22     }
23 
24     public static void main(String [] args)
25     {
26         int  lists[] = new int[] {-2 ,11, -4, 13, -5, -2};
27         System.out.println(MaxSums(lists));
28     }
29 }

第三种方法:分而治之

 1 /**
 2  * @author 小喵钓鱼
 3  * @date 2020-02-02 13:53
 4  * @veision 1.10
 5  *  方法三:分而治之。
 6  * 将序列从中分为左右两个子序列。
 7  * 递归求得两个子列的最大和。
 8  * 从中分点分头向左、右两边扫描,找出跨过分界线的最大子列和。
 9  * 输出这三个子列和最大的一个。
10  */
11 public class MaxSum3 {
12     // 比较三个数的
13     public static  int Max3(int A, int B, int C)
14     {
15         return (A>B)?(A>C?A:C):(B>C?B:C);
16     }
17 
18     /**
19      * 分治 list[left] 和 list[right] 的最大子列和
20      * @param List
21      * @param left
22      * @param right
23      * @return
24      */
25     public static int DivideAndConquer(int List[], int left, int right)
26     {
27         int MaxLeftSum, MaxRightSum;    //存放左右子问题的解。
28         int MaxLeftBorderSum, MaxRightBorderSum;    //存放跨分界线的结果。
29 
30         int LeftBorderSum, RightBorderSum;
31         int center, i;
32 
33         /*递归的终止条件,子列只有1个数字*/
34         if ( left == right ) {
35             if ( List[left] > 0 )    return List[left];
36             else return 0;
37         }
38 
39         /* “分”的过程 */
40         center = ( left + right ) / 2;    //找到中分点。
41         MaxLeftSum = DivideAndConquer ( List, left, center );    //递归求左子列和。
42         MaxRightSum = DivideAndConquer ( List, center+1, right );    //递归求右子列和。
43 
44         /*求跨分界线的最大子列和*/
45         MaxLeftBorderSum = 0;    LeftBorderSum = 0;
46         for ( i = center; i >= left; i-- ) {
47             LeftBorderSum += List[i];
48             if ( LeftBorderSum > MaxLeftBorderSum )
49                 MaxLeftBorderSum = LeftBorderSum;
50         }//左边扫描结束。
51 
52         MaxRightBorderSum = 0;    RightBorderSum = 0;
53         for ( i = center+1; i <= right; i++ ) {
54             RightBorderSum += List[i];
55             if ( RightBorderSum > MaxRightBorderSum )
56                 MaxRightBorderSum = RightBorderSum;
57         }//右边扫描结束。
58 
59         /*返回“治”的结果*/
60         return Max3(MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum );
61     }
62 
63     /*此函数用于保持接口相同*/
64     public static int MaxSum3 ( int List[], int N ) {
65         return DivideAndConquer(List, 0, N - 1);
66     }
67 
68     public static void main(String[] args) {
69         int  lists[] = new int[] {-2 ,11, -4, 13, -5, -2};
70         System.out.println(MaxSum3(lists, lists.length));
71     }
72 }

 

二、Maximum Subsequence Sum (最大序列和,此题和上题比较类似)

Given a sequence of K integers { N1​​, N2​​, ..., NK​​ }. A continuous subsequence is defined to be { Ni​​, Ni+1​​, ..., Nj​​ } where 1. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:

Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (≤). The second line contains K numbers, separated by a space.

Output Specification:

For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:

10
-10 1 2 3 4 -5 -23 3 7 -21
 

Sample Output:

10 1 4
 1 /**
 2  * @author 小喵钓鱼
 3  * @date 2020-02-02 14:28
 4  * @veision 1.10
 5  */
 6 public class Maximum {
 7     public static void Maximums(int list[], int N)
 8     {
 9         int ThisSum, MaxSum, Forntdata, Enddata;
10         int sublen;  // 设置 子列差
11         sublen = Forntdata = Enddata = ThisSum = 0;
12         MaxSum = -1;
13         for (int i = 0; i < N; i++)
14         {
15             ThisSum += list[i];
16             sublen ++;  // 差 + 1
17             if (ThisSum > MaxSum)  // 如果子列和大于最大子列和
18             {
19                 MaxSum = ThisSum;  // 最大和
20                 Enddata = list[i];  // 结尾子序列数据
21                 Forntdata = list[i - sublen + 1];  // 开始子序列数据
22             }
23             if (ThisSum < 0)  // 如果子列和 < 0
24             {
25                 ThisSum = 0;
26                 sublen = 0;
27             }
28         }
29 
30         if (MaxSum < 0)
31         {
32             System.out.println(0 + " " + list[0] + " " + list[N - 1]);
33         }
34         else
35         {
36             System.out.println(MaxSum + " " + Forntdata + " " + Enddata);
37         }
38     }
39 
40     public static void main(String[] args) {
41         int list [] = new int[]{-10, 1, 2, 3, 4, -5, -23, 3, 7, -21};
42         int N = list.length;
43         Maximums(list, N);
44     }
45 }

 

三、二分查找

  顾名思义,就是从中间比较,不断分,来进行查找的一种方法,但是缺点是查找的子序列必须是已经排好序了的

 1 /**
 2  * @author 小喵钓鱼
 3  * @date 2020-02-02 14:38
 4  * @veision 1.10
 5  */
 6 public class binary_search {
 7     public static int binary_search_pp(int list[], int searchKey)
 8     {
 9         int Center;  // 中间坐标
10         int lower = 0;
11         int upper = list.length - 1;
12         while (true)
13         {
14             Center = (lower + upper) / 2;  // 更新
15             if (list[Center] == searchKey){  // 如果第一次就找到,直接返回
16                 return Center;
17             }
18 
19             else if(lower > upper)  // 如果最低坐标,比最高坐标大,那么代表这个数组就一个元素
20             {
21                 return list.length;
22             }
23             else {
24                 if (list[Center] < searchKey)  // 如果 <
25                     lower = Center + 1;
26                 else  // 如果 大
27                     upper = Center - 1;
28             }
29         }
30     }
31 
32     public static void main(String[] args) {
33         int key [] = new int[]{1, 2, 3, 4 ,5 ,6};
34         System.out.println(binary_search_pp(key, 3));
35     }
36 }

 

四、两个有序链表序列的合并

 怎么说呢,感觉自己写的有点小问题,不过无伤大雅,虽然是倒叙就是了,不过思路还是可以借鉴的

    虽然是用 Java写的,但是并没有用到 相应的库,自行写的 单向链表类。

  1 /**
  2  * @author 小喵钓鱼
  3  * @date 2020-02-02 14:59
  4  * @veision 1.10
  5  * L1和L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1和L2合并为一个非递减的整数序列。应直接使用原序列中的结点,返回归并后的带头结点的链表头指针。
  6  */
  7 public class Link{
  8     public int iData;  // data item
  9     public double dData; // data item
 10     public Link next;  // next link in list
 11     public Link(int id, double dd)
 12     {
 13         iData = id;  // initializa data
 14         dData = dd;
 15     }
 16     public void displayLink()
 17     {
 18         System.out.println("{" + iData + ", " + dData + "}");
 19     }
 20 }
 21 
 22 
 23 class LinkList {
 24     private Link first; // ref to first link on list
 25 
 26     public void LinkList() {
 27         first = null;
 28     }
 29 
 30     public boolean isEmpty() {
 31         return (first == null);
 32     }
 33 
 34     public void insertFirst(int id, double dd) {
 35         Link newLink = new Link(id, dd);
 36         newLink.next = first; // newLink --> old first
 37         first = newLink;  // first --> newLink
 38     }
 39 
 40     public Link deleteFirst() {
 41         Link temp = first;
 42         first = first.next;
 43         return temp;
 44     }
 45 
 46     public void displayList() {
 47         System.out.println("List(first --> last)");
 48         Link current = first;  // start at beginning of list
 49         while (current != null) {
 50             current.displayLink();  // print data
 51             current = current.next;  // move to next link
 52         }
 53         System.out.println(" ");
 54     }
 55 
 56     public Link find(int Key) {
 57         Link current = first;
 58         while (current.dData != Key) {
 59             if (current.next == null)
 60                 return null;  // didn't find it
 61             else
 62                 current = current.next;
 63         }
 64         return current;
 65     }
 66 
 67     public void Merge(LinkList L1)
 68     {
 69         LinkList L =  new LinkList();
 70         Link pa, pb, pc;
 71         pa = first;
 72         pb = L1.first;
 73         pc = L.first;
 74         int count = 0;
 75         while (pa != null && pb != null)
 76         {
 77             System.out.println(pa.dData + "=" + pb.dData);
 78             if (pa.dData >= pb.dData)
 79             {
 80                 if (count < 1)
 81                 {
 82                     L.first = pa;
 83                     count ++;
 84                 }
 85                 else {
 86                     pc.next = pa;
 87                 }
 88                 pc = pa;
 89                 pa = pa.next;
 90             }
 91             else {
 92                 if (count < 1)
 93                 {
 94                     L.first = pb;
 95                     count++;
 96 //                    pc .next = pb;
 97                 }
 98                 else {
 99                     pc.next = pb;
100                 }
101                 pc = pb;
102                 pb = pb.next;
103             }
104         }
105 
106         pc.next = pa != null? pa: pb;
107         L1.first = null;
108         this.first = L.first;
109     }
110 }
111 
112 class LinkListApp{
113     public static void main(String [] args)
114     {
115         LinkList theList = new LinkList();  // make new list
116 
117         theList.insertFirst(1, 2.29); // insert four items
118         theList.insertFirst(4, 4.29);
119         theList.insertFirst(6, 6.99);
120         theList.insertFirst(7, 8.99);
121 
122 
123         LinkList nextList = new LinkList();
124         nextList.insertFirst(2, 2.30);
125         nextList.insertFirst(3, 3.40);
126         nextList.insertFirst(5, 5.33);
127 
128 
129         theList.Merge(nextList);
130         theList.displayList();
131     }
132 }

 

五、一元多项式的乘法与加法运算

设计函数分别求两个一元多项式的乘积与和。

输入格式:

输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式:

输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0

输入样例:

4 3 4 -5 2  6 1  -2 0
3 5 20  -7 4  3 1
 

输出样例:

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

代码示例

  1 /**
  2  * @author 小喵钓鱼
  3  * @date 2020-02-02 18:18
  4  * @veision 1.10
  5  * 设计函数分别求两个一元多项式的乘积与和。
  6  *
  7  * 输入格式:
  8  * 输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
  9  *
 10  * 输出格式:
 11  * 输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。
 12  */
 13 class Links
 14     {
 15         public int iData;
 16         public int dData;
 17         public Links next;  // next Link
 18         public Links(int id, int dd)
 19         {
 20             iData = id;
 21             dData = dd;
 22         }
 23 
 24         public void displayLink()
 25         {
 26             System.out.println("{" + iData + ":" + dData + "}");
 27         }
 28 
 29         public void setId(int id)
 30         {
 31             this.iData = id;
 32         }
 33     }
 34 class LinkList{
 35     public Links first;  // ref to the first link
 36     public Links last;  // ref to the last link
 37 
 38     public void LinkList()
 39     {
 40         first = null;
 41         last = null;
 42     }
 43 
 44     public boolean isEmpty()
 45     {
 46         return (first == null);
 47     }
 48 
 49     public void insertFirst(int id, int dd)
 50     {
 51         Links newLink = new Links(id, dd);
 52         if (isEmpty())
 53         {
 54             last = newLink;   // newLink <-- last
 55         }
 56         newLink.next = first;  // newLink --> old first
 57         first = newLink;
 58     }
 59 
 60     public void insertAfter(int id, int dd)
 61     {
 62         Links newLink = new Links(id, dd);
 63         if (isEmpty())
 64         {
 65             first = newLink;  // first --> newLink
 66         }
 67         else
 68             last.next = newLink;  // old last --> newLink
 69         last = newLink;  // newLink <-- last
 70     }
 71 
 72     public void displayLink()
 73     {
 74         System.out.println("List(first --> last)");
 75         Links current = first;  // start at beginning of list
 76         while (current != null) {
 77             current.displayLink();  // print data
 78             current = current.next;  // move to next link
 79         }
 80         System.out.println(" ");
 81     }
 82 
 83 }
 84 public class Mult_Add {
 85     public static void ReadOnly(LinkList P1)
 86     {
 87         Scanner scanner = new Scanner(System.in);
 88         int N = scanner.nextInt();  // 位数
 89         for (int i = 0; i < N; i++)
 90         {
 91             int idata = scanner.nextInt();
 92             int ddata = scanner.nextInt();
 93             P1.insertAfter(idata, ddata);
 94     }
 95     }
 96 
 97     public static LinkList Add(LinkList T1, LinkList T2)
 98     {
 99         LinkList P = new LinkList();
100 
101         if (T1 == null || T2 == null)
102         {
103             return null;
104         }
105         // 分别指向 T1, T2 的第一个元素
106         Links link1 = T1.first;
107         Links link2 = T2.first;
108 
109         while (link1 != null && link2 != null) {  // 两者均不为空时
110             if (link1.dData > link2.dData) {
111                 P.insertAfter(link1.iData, link1.dData);
112                 link1 = link1.next;
113             }
114             else if(link1.dData<link2.dData)
115             {
116                 P.insertAfter(link2.iData, link2.dData);
117                 link2 = link2.next;
118             }
119             else {  // 两者指数相等时
120                     if (link1.iData + link2.iData != 0) {
121                         P.insertAfter(link1.iData + link2.iData, link1.dData);
122                     }
123                     link1 = link1.next;
124                     link2 = link2.next;
125             }
126         }
127 
128         while (link1 != null)
129         {
130             P.insertAfter(link1.iData, link1.dData);
131             link1 = link1.next;
132         }
133         while (link2 != null)
134         {
135             P.insertAfter(link2.iData, link2.dData);
136             link2 = link2.next;
137         }
138         return P;
139     }
140 
141 
142     public static LinkList Mult(LinkList T1, LinkList T2)
143     {
144       LinkList P = new LinkList();
145       // 分别指向第一个元素
146       Links link1 = T1.first;
147       Links link2 = T2.first;
148 
149         /**
150          * 这里用的方法是先将两者每一个都像乘法那样相乘,然后进行同类项的合并
151          */
152         while (link1 != null)
153       {
154           while (link2 != null)
155           {
156               int idata = link1.iData * link2.iData;
157               int ddata = link1.dData + link2.dData;
158               P.insertAfter(idata, ddata);
159               link2 = link2.next;
160           }
161           link1 = link1.next;
162           link2 = T2.first;
163       }
164 
165       // 合并同类项
166       Links link3 = P.first;  // 指向 P 的 第一个元素
167       Links tempPrevious = link3;  // 同指
168       Links temp = link3.next;  // 指向第二个元素
169       while (link3.next != null)  // 当Link3 不等于 last 时。。。
170       {
171           while (temp != null)
172           {
173               if (temp.dData != link3.dData)  // 如果 前一个和后一个的指数不同,则都向下进一个
174               {
175                   temp = temp.next;
176                   tempPrevious = tempPrevious.next;
177               }
178               else  // 如果两者指数相同
179               {
180                   link3.setId(link3.iData + temp.iData);  // 更改前者系数
181                   tempPrevious.next = temp.next; // 将 前者改成 temp
182                   temp = temp.next;  // temp = temp.next
183               }
184           }
185           link3 = link3.next;  
186           tempPrevious = link3;
187           temp = link3.next;
188       }
189       return P;
190     }
191 
192     public static void main(String[] args) {
193         LinkList p1 = new LinkList();
194         ReadOnly(p1);
195         p1.displayLink();
196 
197         LinkList p2 = new LinkList();
198         ReadOnly(p2);
199         p2.displayLink();
200         LinkList P = Add(p1, p2);
201         P.displayLink();
202 
203         LinkList P3 = Mult(p1, p2);
204         P3.displayLink();
205     }
206 }
posted @ 2020-02-03 16:22  小喵钓鱼  阅读(198)  评论(0编辑  收藏  举报