实验目的和要求
(1)进一步掌握递归算法的设计思想以及递归程序的调试技术;
(2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。
(3)分别用蛮力法和分治法求解最近对问题;
(4)分析算法的时间性能,设计实验程序验证分析结论。
实验内容
1、给定由n个整数组成的序列(a1, a2, …, an),最大子段和问题要求该序列形如ai+…+aj 的最大值(1≤i≤j≤n),当序列中所有整数均为负整数时,其最大子段和为0。
2、在一个2k×2k (k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。棋盘覆盖问题要求用4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
实验环境
VS2010 或VC++
实验学时
2学时,必做实验
数据结构与算法
- 最大字段和:
数据结构:
存储数据序列用数组a[]表示
Lefts表示左半部分字段和
Rights表示右半部分字段和
Midsum表示新字段和
算法:分治算法
- 骨牌覆盖
数据结构:
棋盘用二维数组board[size][size]表示,size=2^k
特殊方格用用二维数组board[dr][dc]表示
L型骨牌:个数为(4^k-1)/3,用t表示
算法:分治算法
核心源代码
1.最大字段和:
#include<stdio.h>
int MaxSum(int a[],int left,int right){
int sum = 0,midsum = 0,leftsum = 0,rightsum = 0;
int center;
int s1 = 0,s2 = 0,lefts = 0,rights = 0;
if(left == right)
sum = a[left];
else{
center = (left+right)/2;
leftsum = MaxSum(a,left,center);
rightsum = MaxSum(a,center+1,right);
for(int i = center;i>=left;i--){
lefts += a[i];
if(lefts > s1)
s1 = lefts;
}
for(int j = center + 1;j <= right;j++){
rights +=a[j];
if(rights > s2)
s2 = rights;
}
midsum = s1+s2;
if(midsum<leftsum)
sum = leftsum;
else
sum = midsum;
if(sum<rightsum)
sum = rightsum;
}
return sum;
}
int main()
{
int a[100],n;
printf("请输入序列的个数:");
scanf("%d",&n);
printf("请输入序列的各数值:");
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int b = MaxSum(a,0,n-1);
printf("%d",b);
}
2.骨牌覆盖:
#include<stdio.h>
int board[100][100];
int t=0;
void ChessBoard(int tr,int tc,int dr,int dc,int size){
int s=0,t1;
if(size==1)
return;
t1=++t;
s=size/2;
//左上角
if(dr<tr+s && dc<tc+s)
ChessBoard(tr,tc,dr,dc,s);
else{
board[tr+s-1][tc+s-1] = t1;
ChessBoard(tr,tc,tr+s-1,tc+s-1,s);
}
//右上角
if(dr<tr+s &&dc>=tc+s)
ChessBoard(tr,tc+s,dr,dc,s);
else{
board[tr+s-1][tc+s] = t1;
ChessBoard(tr,tc+s,tr+s-1,tc+s,s);
}
//左下角
if(dr>=tr+s && dc<tc+s)
ChessBoard(tr+s,tc,dr,dc,s);
else{
board[tr+s][tc+s-1] = t1;
ChessBoard(tr+s,tc,tr+s,tc+s-1,s);
}
//右下角
if(dr>=tr+s && dc>=tc+s)
ChessBoard(tr+s,tc+s,dr,dc,s);
else{
board[tr+s][tc+s] = t1;
ChessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}
int main(){
int size,dr,dc;
printf("请输入棋盘size大小(size为2的k次方):");
scanf("%d",&size);
printf("请输入特殊棋子的行序号:");
scanf("%d",&dr);
printf("请输入特殊棋子的列序号:");
scanf("%d",&dc);
ChessBoard(0,0,dr,dc,size);
for(int i = 0;i<size;i++){
for(int j = 0;j<size;j++){
printf("%2d ",board[i][j]);
}
printf("\n");
}
return 0;
}
力扣169:
Class Solution {
public int majorityElement(int[] nums) {
return find_num(nums,0,nums.length-1);
}
int find_num(int[] nums,int left,int right){
if(left==right)
return nums[left];
int middle = (left+right)/2;
int lefts = find_num(nums,left,middle);
int rights = find_num(nums,middle+1,right);
if(lefts==rights)
return lefts;
else{
int count = 0;
for(int i = left;i<=right;i++){
if(nums[i]==lefts)
count++;
if(nums[i]==rights)
count--;
}
if(count>0)
return lefts;
else
return rights;
}
}
}
实验结果
1.最大字段和:
2.骨牌覆盖:
- 力扣169