整数划分问题
整数划分问题:将一个整数划分为若干个数相加
例子:
整数4 最大加数 4
4=4
1+3=4
1+1+2=4
2+2=4
1+1+1+1=4
一共五种划分方案
注意:1+3=4,3+1=4被认为是同一种划分方案
最后输出共几种划分方案
#include <stdio.h>
int q(int n, int m) {
if (m == 1 || n == 1) {
return 1;
} else if (n == m && n > 1) {
return q(n, n - 1) + 1;
} else if (n < m) {
return q(n, n);
} else if (n > m) {
return q(n, m - 1) + q(n - m, m);
}
return 0;
}
int main() {
printf("请输入需要划分的数字和最大加数:\n");
int n, m;
scanf("%d %d", &n, &m);
int r = q(n, m);
printf("%d\n", r);
return 0;
}
使用减治法计算多边形的面积
给定一个多边形的顶点坐标,要求使用减治法计算该多边形的面积。
要求:
1.实现一个函数 double calculateArea(double x[], double y[], int n),其中 x[] 和 y[] 分别是多边形各顶点的 x 坐标和 y 坐标数组,n 是多边形的顶点个数。
2.使用减治法思想,将多边形分解为三角形,计算每个三角形的面积,然后将所有三角形的面积相加得到多边形的面积。
3.返回多边形的面积。
#include <stdio.h>
#include <math.h>
double triangleArea(double x1, double y1, double x2, double y2, double x3, double y3) {
return fabs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2.0);
}
double calculateArea(double x[], double y[], int n) {
double area = 0.0;
for (int i = 1; i < n - 1; i++) {
area += triangleArea(x[0], y[0], x[i], y[i], x[i + 1], y[i + 1]);
}
return area;
}
int main() {
int n;
printf("请输入多边形的顶点个数:");
scanf("%d", &n);
double x[n], y[n];
printf("请输入多边形的各顶点坐标:\n");
for (int i = 0; i < n; i++) {
printf("顶点%d的坐标(x,y):", i + 1);
scanf("%lf %lf", &x[i], &y[i]);
}
//计算多边形的面积
double area = calculateArea(x, y, n);
printf("多边形的面积为:%.2lf\n", area);
return 0;
}
拿子游戏
拿子游戏是一个经典的博弈论问题,有一个堆中有一定数量的子,两个玩家轮流从中取子,每次可以取走 1 到 k 个子,最后无法取子的一方判负。现在要求你使用分治法或减治法来解决这个问题。
要求:
1.实现一个函数 int canWin(int n, int k),其中 n 是初始子的数量,k 是每次最多可以取走的子的数量。
2.使用分治法或减治法思想,递归地判断当前玩家是否能赢得游戏。
3.返回值为 1 表示当前玩家能赢得游戏,返回值为 0 表示当前玩家无法赢得游戏。
#include<stdio.h>
#include <limits.h>
int canWin(int n, int k)
{
if(n<=k)
return 1;
if(n%(k+1)==0)
return 0;
return !canWin(n-(n%(k+1)),k);
}
int main(){
int n,k;
printf("请输入初始子的数量n和每次最多可以取走的子的数量k:\n");
scanf("%d %d",&n,&k);
int result=canWin(n,k);
if(result){
printf("当前玩家能赢得游戏!\n");
}
else{
printf("当前玩家无法赢得游戏!\n");
}
return 0;//请在此处开始编写你的代码
}
棋盘覆盖问题
棋盘覆盖问题是一个经典的计算几何问题,给定一个 2^k x 2^k 的棋盘和一个特殊方块,要求用特殊方块覆盖整个棋盘,其中特殊方块除了一个缺口外都是完整的 L 形。现在要求你使用分治法或减治法来解决这个问题。
要求:
1.实现一个函数 void chessboardCover(int board[][MAX], int tr, int tc, int dr, int dc, int size),其中 board 是二维数组表示棋盘,tr 和 tc 是棋盘左上角的行和列,dr 和 dc 是特殊方块的缺口所在的行和列,size 是当前棋盘的大小。
2.使用分治法或减治法思想,将棋盘划分为四个等大小的子棋盘,递归地覆盖子棋盘,直到覆盖完整个棋盘。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int num = 0,x=2;
int Matrix[100][100];
void chessBoard(int tr, int tc, int dr, int dc, int size);
int main()
{
int size,r,c,row,col;
//printf("请输入棋盘的行列号");
scanf("%d",&size);
size= pow(x,size);
//printf("请输入特殊方格的行列号");
scanf("%d %d",&row,&col);
chessBoard(0,0,row,col,size);
for (r = 0; r < size; r++)
{
for (c = 0; c < size; c++)
{
printf("%2d ",Matrix[r][c]);
}
printf("\n");
}
return 0;
}
void chessBoard(int tr, int tc, int dr, int dc, int size)
{
int s,t;
if (size==1) return;
s = size/2; //分割棋盘
t = ++num; //L型骨牌号
if (dr < tr + s && dc < tc +s) //覆盖左上角子棋盘
{
//特殊方格在此棋盘中
chessBoard(tr,tc,dr,dc,s);
}
else //此棋盘中无特殊方格
{
//用t号L型骨牌覆盖右下角
Matrix[tr+s-1][tc+s-1] = t;
//覆盖其余方格
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 //此棋盘中无特殊方格
{
//用t号L型骨牌覆盖左下角
Matrix[tr+s-1][tc+s] = t;
//覆盖其余方格
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
{
//用t号L型骨牌覆盖右上角
Matrix[tr+s][tc+s-1] = t;
//覆盖其余方格
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
{
//用t号L型骨牌覆盖左上角
Matrix[tr+s][tc+s] = t;
//覆盖其余方格
chessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}
分治法找到数组中出现次数超过一半的元素
分治法找到数组中出现次数超过一半的元素
#include<stdio.h>
int findCandidate(int arr[],int n){
int candidate=arr[0];
int count=1;
for(int i=1;i<n;i++){
if(arr[i]==candidate){
count++;
}else{
count--;
}
if(count==0){
candidate=arr[i];
count=1;
}
}
return candidate;
}
int findMajorityElement(int arr[],int n){
int candidate=findCandidate(arr,n);
int count=0;
for(int i=0;i<n;i++){
if(arr[i]==candidate){
count++;
}
}
if(count>n/2){
return candidate;
}else{
return -1;
}
}
int main(){
int n;
scanf("%d",&n);
int arr[n];
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
}
int majorityElement=findMajorityElement(arr,n);
if(majorityElement!=-1){
printf("The majority element in the array:%d\n",majorityElement);
}else{
printf("There is no majority element in the array.\n");
}
return 0;
}
减治法计算数组中的零个数
给定一个整数数组,使用减治法计算数组中的零个数
#include<stdio.h>
#include <limits.h>
int main(int argc ,char const *argv[]){
//请在此处开始编写你的代码
int len;
int zero =0;
scanf("%d",&len);
int arr[len];
for(int i =0;i<len;i++){
scanf("%d",&arr[i]);
}
for(int i=0;i<len;i++){
if(arr[i]==0){
zero++;
}
}
printf("%d",zero);
return 0;
}
分治法计算数组中的负数个数
给定一个整数数组,使用分治法计算数组中的负数个数
#include <stdio.h>
int main(int argc, char const *argv[]) {
int len;
int fu = 0;
scanf("%d", &len);
int arr[len];
for (int i = 0; i < len; i++) {
scanf("%d", &arr[i]);
}
for (int i = 0; i < len; i++) {
if (arr[i] < 0) {
fu++;
}
}
printf("The number of negative elements in the array is:%d", fu);
return 0;
}
减治法计算数组中的正数个数
给定一个整数数组,使用减治法计算数组中的正数个数
#include<stdio.h>
#include <limits.h>
int countPositive(int arr[],int n)
{
if(n==0){
return 0;
}else{
if(arr[n-1]>0){
return 1+countPositive(arr,n-1);
}else{
return countPositive(arr,n-1);
}
}
}
int main(){
int n;
printf("Enter the size of the array:");
scanf("%d",&n);
int arr[n];
printf("Enter the elements of the array:");
for(int i=0;i<n;i++)
{
scanf("%d",&arr[i]);
}
int count = countPositive(arr,n);
printf("the number of positive elements in the array is:%d\n",count);
return 0;
//请在此处开始编写你的代码
}
分治法计算数组中的奇数个数
给定一个整数数组,使用分治法计算该数组中奇数的个数。
#include <limits.h>
#include <stdio.h>
int countOdd(int arr[], int low, int high) {
if (low > high) {
return 0;
} else if (low == high) {
return arr[low] % 2 != 0 ? 1 : 0;
} else {
int mid = (low + high) / 2;
int leftCount = countOdd(arr, low, mid);
int rightCount = countOdd(arr, mid + 1, high);
return leftCount + rightCount;
}
}
int main() {
int n;
printf("Enter the size of the array: ");
scanf("%d", &n);
int arr[n];
printf("Enter the elements of the array: ");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
int count = countOdd(arr, 0, n - 1);
printf("The number of odd elements in the array is: %d\n", count);
return 0;
}
减治法计算数组中的偶数个数
给定一个整数数组,使用减治法计算该数组中偶数的个数。
要求:
1.实现一个函数 int countEven(int arr[], int size),其中 arr 是整数数组,size 是数组的大小。
2.使用减治法思想,在每一步将问题规模减小,直到得到基本问题的解。
3.返回数组中偶数的个数。
#include<stdio.h>
int countEven(int arr[],int n){
if(n==0){
return 0;
}else{
if(arr[n-1]%2==0){
return 1+countEven(arr,n-1);
}else{
return countEven(arr,n-1);
}
}
}
int main(){
int n;
printf("Enter the size of the array:");
scanf("%d",&n);
int arr[n];
printf("Enter the element of the array:");
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
}
int count=countEven(arr,n);
printf("The number of even elements in the array is:%d\n",count);
return 0;
}
减治法求数组的平均值
给定一个整数数组,用减治法求数组的平均值
#include <stdio.h>
#include <limits.h>
int main(int argc, char const *argv[]) {
//请在此处开始编写你的代码
int len;
int sum = 0;
scanf("%d", &len);
int arr[len];
for (int i = 0; i < len; i++) {
scanf("%d", &arr[i]);
}
for (int i = 0; i < len; i++) {
sum += arr[i];
}
double aver = sum * 1.0 / len;
printf("%.2f", aver);
return 0;
}
与对应负数同时存在的最大正整数
给定一个包含正整数和负整数的数组,找出数组中与每个负数对应的最大正整数,并返回这些最大正整数的和。要求使用分治法或减治法来解决此问题。
#include <stdio.h>
// 获取数组中与负数对应的最大正整数
int getMaxPositive(int nums[], int left, int right) {
// 如果数组为空,返回 0
if (left > right) return 0;
// 如果数组中只有一个元素,且为正数,则返回该正数;否则返回 0
if (left == right) {
if (nums[left] > 0) return nums[left];
else return 0;
}
// 计算数组中间元素的索引
int mid = left + (right - left) / 2;
// 递归求解左右子数组的最大正整数
int leftMax = getMaxPositive(nums, left, mid);
int rightMax = getMaxPositive(nums, mid + 1, right);
// 计算跨越中间元素的最大正整数
int crossMax = 0;
int sum = 0;
for (int i = mid; i >= left; i--) {
sum += nums[i];
if (sum > crossMax) crossMax = sum;
}
sum = 0;
for (int i = mid + 1; i <= right; i++) {
sum += nums[i];
if (sum > crossMax) crossMax = sum;
}
// 返回三者中的最大值
return (leftMax > rightMax) ? ((leftMax > crossMax) ? leftMax : crossMax) : ((rightMax > crossMax) ? rightMax : crossMax);
}
int main() {
int nums[] = {1, -2, 3, -4, 5};
int size = sizeof(nums) / sizeof(nums[0]);
// 计算与负数对应的最大正整数的和
int maxPositiveSum = 0;
for (int i = 0; i < size; i++) {
if (nums[i] < 0) {
maxPositiveSum += getMaxPositive(nums, i + 1, size - 1);
}
}
printf("与对应负数同时存在的最大正整数的和为:%d\n", maxPositiveSum);
return 0;
}
数组元素与数字和的绝对差
给定一个整数数组和一个目标值,找出数组中所有元素与目标值的绝对差最小的元素,并输出它们的绝对差值。
#include<stdio.h>
#include<stdlib.h>
#include <limits.h>
typedef struct{
int value;
int abs_diff;
}Element;
int compare(const void *a,const void *b)
{
return((Element*)a)->abs_diff-((Element*)b)->abs_diff;
}
void findClosestElements(int arr[],int n,int target){
Element elements[n];
for(int i=0;i<n;i++)
{
elements[i].value=arr[i];
elements[i].abs_diff=abs(arr[i]-target);
}
qsort(elements,n,sizeof(Element),compare);
printf("与目标值的绝对差最小的元素为:\n");
for(int i=0;i<n;i++)
{
if(elements[i].abs_diff==elements[0].abs_diff){
printf("%d(数组中与目标值的绝对差最小的元素的绝对差值:%d)\n",elements[i].value,elements[i].abs_diff);
}else{
break;
}
}
}
int main(){
int n;
printf("请输入数字的大小:");
scanf("%d",&n);
int arr[n];
printf("请输入数组元素:");
for(int i=0;i<n;i++)
{
scanf("%d",&arr[i]);}
int target;
printf("请输入目标值:");
scanf("%d",&target);
findClosestElements(arr,n,target);
return 0;
//请在此处开始编写你的代码
}
最小高度树
给定一个已排序(升序)的整数数组,构建一棵高度最小的二叉搜索树(BST)。高度最小的定义是树中任意节点到根节点的距离最小。编写一个程序,在给定的整数数组中构建高度最小的二叉搜索树,并返回根节点。
#include <limits.h>
//请在此处开始编写你的代码
#include <stdio.h>
#include <stdlib.h>
// 二叉树节点结构
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
};
// 构建高度最小的二叉搜索树
struct TreeNode* sortedArrayToBST(int* nums, int start, int end) {
// 边界情况处理
if (start > end) return NULL;
// 找到中间元素的索引
int mid = start + (end - start) / 2;
// 创建当前节点,并赋值
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
root->val = nums[mid];
// 递归构建左子树
root->left = sortedArrayToBST(nums, start, mid - 1);
// 递归构建右子树
root->right = sortedArrayToBST(nums, mid + 1, end);
return root;
}
// 中序遍历打印二叉树
void inorderTraversal(struct TreeNode* root) {
if (root) {
inorderTraversal(root->left);
printf("%d ", root->val);
inorderTraversal(root->right);
}
}
int main() {
int nums[] = {-10, -3, 0, 5, 9};
int numsSize = sizeof(nums) / sizeof(nums[0]);
// 构建高度最小的二叉搜索树
struct TreeNode* root = sortedArrayToBST(nums, 0, numsSize - 1);
// 打印构建的二叉搜索树
printf("构建的高度最小的二叉搜索树:");
inorderTraversal(root);
printf("\n");
return 0;
}
减治法实验怎么利用小车才能让两人尽快到达
两人A和B要从城市的起点到终点,城市中有一条笔直的道路,两边有沙漠地带无法行走。他们有一辆小车,但小车只能容纳一人。为了尽快到达目的地,他们决定采用减治法的策略:一人驾驶小车前进,另一人留在原地等待。当小车到达终点后,留在原地的人会驾驶小车返回,再接另一个人继续前进,直到两人都到达终点。编写一个程序,根据两人的起点和终点位置,以及小车的速度,计算两人最快到达终点的时间。
#include<stdio.h>
float fastestTime(int startA,int startB,int endA,int endB,int speedCar){
int distanceToAEnd=endA-startA;
int distanceToBEnd=endB-startB;
float timeToAEnd=(float)distanceToAEnd/speedCar;
float timeToBEnd=(float)distanceToBEnd/speedCar;
return timeToAEnd>timeToBEnd?timeToAEnd:timeToBEnd;
}
int main(){
int startA,startB,endA,endB,speedCar;
printf("请输入A的起点位置:");
scanf("%d",&startA);
printf("请输入B的起点位置:");
scanf("%d",&startB);
printf("请输入A终点位置:");
scanf("%d",&endA);
printf("请输入B的终点位置:");
scanf("%d",&endB);
printf("请输入小车的速度:");
scanf("%d",&speedCar);
float time=fastestTime(startA,startB,endA,endB,speedCar);
printf("最快到达终点的时间:%.1f 小时\n",time);
return 0;
}
减治算法实现8枚硬币问题
给定8枚硬币,其中7枚重量相等,1枚重量稍微不同。要求使用减治算法找出这枚重量不同的硬币,并确定它是轻一些还是重一些。
输入格式:
输入8个正整数,这8个数代表的就是硬币的重量,要求有7个正整数相同,1个不同。
#include <stdio.h>
#include <math.h>
int main() {
int a[8];
int a1, b, numa, numb;
numa = 0;
numb = 0;
for (int i = 0; i < 8; i++) {
scanf("%d", &a[i]);
}
a1 = a[0];
numa++;
for (int i = 1; i < 8; i++) {
if (a[i] == a1) {
numa++;
} else {
b = a[i];
numb++;
}
}
int c;
if (numa < numb) {
c = a1;
} else {
c = b;
}
for (int i = 0; i < 8; i++) {
if (a[i] == c) {
printf("编号:%d ", i+1);
if (a[i] > a[i - 1]) {
printf("重量:较重");
} else {
printf("重量:较轻");
}
break;
}
}
return 0;
}
使用减治法解决堆排序
堆排序是一种经典的排序算法,基于二叉堆的数据结构。给定一个包含N个整数的数组,现在要求你使用堆排序算法对这个数组进行排序。请编写一个程序,用减治法实现堆排序算法。
输入格式:
1.第一行包含一个整数 N (1 ≤ N ≤ 10^6),表示数组中整数的个数。
2.第二行包含 N 个整数,表示待排序的数组,每个整数的范围为 [-10^9, 10^9]。
#include <limits.h>
//请在此处开始编写你的代码
#include <stdio.h>
// 交换数组中两个元素的位置
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 调整堆使得以root为根的子树成为最大堆
void heapify(int arr[], int n, int root) {
int largest = root; // 初始化根节点为最大值
int left = 2 * root + 1;
int right = 2 * root + 2;
// 如果左子节点比根节点大,则更新最大值的索引
if (left < n && arr[left] > arr[largest]) {
largest = left;
}
// 如果右子节点比根节点大,则更新最大值的索引
if (right < n && arr[right] > arr[largest]) {
largest = right;
}
// 如果最大值不是根节点,则交换并继续调整堆
if (largest != root) {
swap(&arr[root], &arr[largest]);
heapify(arr, n, largest);
}
}
// 堆排序算法
void heapSort(int arr[], int n) {
// 构建最大堆
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
// 从最后一个非叶子节点开始,依次将最大值与最后一个元素交换并调整堆
for (int i = n - 1; i > 0; i--) {
swap(&arr[0], &arr[i]); // 将当前最大值放到数组末尾
heapify(arr, i, 0); // 调整剩余元素使得成为最大堆
}
}
int main() {
int n;
scanf("%d", &n);
int arr[n];
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
heapSort(arr, n);
// 输出排好序的数组元素
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
数字旋转方阵
给定一个N × N 的方阵,每个格子里填有一个整数。现在要求你将这个方阵按照顺时针方向旋转90度。请编写一个程序,实现这个旋转操作。
输入格式:
1.第一行包含一个整数 N (1 ≤ N ≤ 100),表示方阵的大小。
2.接下来 N 行,每行包含 N 个整数,表示方阵中每个格子的值,每个整数的范围为 [-1000, 1000]。
//请在此处开始编写你的代码
#include<stdio.h>
#define MAX_SIZE 100
void rotateMatrix(int matrix[MAX_SIZE][MAX_SIZE],int n){
int rotated[MAX_SIZE][MAX_SIZE];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
rotated[j][n-1-i]=matrix[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
matrix[i][j]=rotated[i][j];
}
}
}
int main(){
int n;
int matrix[MAX_SIZE][MAX_SIZE];
scanf("%d",&n);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
scanf("%d",&matrix[i][j]);
}
}
rotateMatrix(matrix,n);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
printf("%d",matrix[i][j]);
}
printf("\n");
}
return 0;
}
背包问题
有一个背包,容量为 capacity,现有一些物品,每件物品都有自己的重量 weights[i] 和价值 values[i]。需要从这些物品中选择一些放入背包中,使得放入的物品总重量不超过背包的容量,并且使得放入的物品总价值最大化。设计一个程序,求解该背包问题,并输出放入背包的物品及其总价值。
要求:编写一个函数,接受背包容量、物品重量数组和物品价值数组作为输入,并返回最大化的总价值。
输入格式:
一个整数 capacity,表示背包的容量。
物品数量
一个整数数组 weights[],表示每件物品的重量。
一个整数数组 values[],表示每件物品的价值。
//请在此处开始编写你的代码
#include <stdio.h>
#include <stdlib.h>
// 返回两个整数中的较大值
int max(int a, int b) {
return (a > b) ? a : b;
}
// 背包问题的分治法求解函数
int knapsack(int capacity, int weights[], int values[], int n) {
// 如果没有物品或者背包容量为0,则返回0
if (n == 0 || capacity == 0) {
return 0;
}
// 如果当前物品的重量大于背包容量,则跳过该物品
if (weights[n - 1] > capacity) {
return knapsack(capacity, weights, values, n - 1);
}
// 计算包含当前物品和不包含当前物品两种情况下的最大价值
int include = values[n - 1] + knapsack(capacity - weights[n - 1], weights, values, n - 1);
int exclude = knapsack(capacity, weights, values, n - 1);
// 返回两种情况下的最大值
return max(include, exclude);
}
int main() {
int capacity, n;
// 读取背包容量
printf("请输入背包容量:\n");
scanf("%d", &capacity);
// 读取物品数量
printf("请输入物品数量:\n");
scanf("%d", &n);
// 读取物品重量和价值数组
int weights[n], values[n];
printf("请输入物品重量:\n");
for (int i = 0; i < n; i++) {
scanf("%d", &weights[i]);
}
printf("请输入物品价值:\n");
for (int i = 0; i < n; i++) {
scanf("%d", &values[i]);
}
int maxValue = knapsack(capacity, weights, values, n);
printf("最大总价值为:%d\n", maxValue);
return 0;
}
俄式乘法
俄式乘法是一种通过将两个数分别以二进制形式展开,并利用加法和位移运算来实现的乘法方法。该方法的基本思想是将较大的数按位分解为二进制,然后将乘法问题转化为一系列的加法和位移运算。设计一个程序,实现俄式乘法,计算两个给定的正整数的乘积。
要求:编写一个函数,接受两个正整数作为输入,并使用俄式乘法算法来计算它们的乘积。
#include<stdio.h>
#include<math.h>
int getNumDigits(int num){
return(num==0)?1:(int)(log10(num)+1);
}
int russianMultiplication(int a,int b,int digits){
if(a==0||b==0){
return 0;
}
if(digits==1){
return a*b;
}
int a_high=a/(int)pow(10,digits/2);
int a_low=a%(int)pow(10,digits/2);
int b_high=b/(int)pow(10,digits/2);
int b_low=b%(int)pow(10,digits/2);
int p1=russianMultiplication(a_high,b_high,digits/2);
int p2=russianMultiplication(a_high,b_low,digits/2);
int p3=russianMultiplication(a_low,b_high,digits/2);
int p4=russianMultiplication(a_low,b_low,digits/2);
return p1*(int)pow(10,digits)+(p2+p3)*(int)pow(10,digits/2)+p4;
}
int main(){
int a;
int b;
printf("请输入两个正整数:\n");
scanf("%d %d",&a,&b);
int digits=getNumDigits(a>b?a:b);
int product=russianMultiplication(a,b,digits);
printf("俄式乘法:%d*%d=%d\n",a,b,product);
return 0;
}
淘汰冠军问题
有 n 个选手参加一场比赛,每个选手都有一个唯一的正整数编号,并且比赛结果已经确定。现在,你需要设计一个程序来找出淘汰冠军。淘汰冠军的规则如下:选手依次排成一列,第一轮比赛时,第一个选手与第二个选手比赛,第三个选手与第四个选手比赛,以此类推。在每一轮中,编号较大的选手将被淘汰,而编号较小的选手将进入下一轮。如果参加比赛的选手数为奇数,则最后一个选手将直接晋级下一轮。重复以上步骤,直到只剩下一个选手,该选手即为冠军。要求:编写一个函数,接受一个整数数组作为输入,数组中存储了每个选手的编号,并找出淘汰冠军的编号。
#include<stdio.h>
#include <limits.h>
//请在此处开始编写你的代码
// 找出淘汰冠军的函数
int findChampion(int arr[], int n) {
// 当只剩下一个选手时,该选手为冠军
if (n == 1) {
return arr[0];
}
// 用于存储下一轮的选手编号
int nextRound[n / 2];
int j = 0;
// 进行当前轮比赛
for (int i = 0; i < n; i += 2) {
// 当还有两个选手时,较小的选手晋级下一轮
if (i == n - 1) {
nextRound[j] = arr[i];
break;
}
// 较小的选手晋级下一轮
if (arr[i] < arr[i + 1]) {
nextRound[j] = arr[i];
} else {
nextRound[j] = arr[i + 1];
}
j++;
}
// 递归调用,进入下一轮比赛
return findChampion(nextRound, n / 2);
}
int main() {
int n;
printf("Enter the number of players: ");
scanf("%d", &n);
int arr[n];
printf("Enter the player IDs: ");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
int champion = findChampion(arr, n);
printf("淘汰冠军的编号: %d\n", champion);
return 0;
}
减治法求a的n次方
设计一个程序,使用减治法来计算an。
输入格式:
第一行输入底数a的值
第二行输入次方数n
#include <stdio.h>
#include <math.h>
double an(int a,int n){
if(n==1) return a;
else{
if(n%2 == 0)
return pow(an(a, n/2),2);
else
return a*pow( an(a,(n-1)/2) , 2);
}
}
int main(){
int a,n;
scanf("%d",&a);
scanf("%d",&n);
int rs=an(a, n);
printf("%d的%d次方结果为:%d",a,n,rs);
}
使用减治法和递归方法实现插入排序算法
设计一个程序,使用减治法和递归方法实现插入排序算法
#include <stdio.h>
void inserSort(int a[], int n) {
int key = a[n], i;
for(i = n - 1; i >= 0; i--) {
if(a[i] > key) a[i + 1] = a[i];
else break;
}
a[i + 1] = key;
}
void insertionSortRecur(int a[], int n) { //n表示元素的个数
if(n <= 1) return;
insertionSortRecur(a, n - 1); //减小规模
inserSort(a, n - 1);
}
int main() {
int n,a[n];
scanf("%d",&n);
for(int i = 0; i < n; i++) {
scanf("%d ", &a[i]);
}
insertionSortRecur(a, n);
printf("Sorted array: [");
for(int i = 0; i < n; i++) {
printf("%d", a[i]);
if(i != n-1)
{
printf(",");
}
else
{
printf("]");
}
}
return 0;
}
矢量点乘
设计一个程序,实现两个n维向量的点乘运算。向量点乘是指将两个向量中对应位置的元素相乘,并将结果相加得到一个标量值的运算。
#include <limits.h>
//请在此处开始编写你的代码
#include <stdio.h>
#define N 3
// 计算两个矢量的点乘
int dotProduct(int vec1[], int vec2[]) {
int result = 0;
for (int i = 0; i < N; i++) {
result += vec1[i] * vec2[i];
}
return result;
}
int main() {
int vec1[N], vec2[N];
printf("Enter the elements of the first vector: ");
for (int i = 0; i < N; i++) {
scanf("%d", &vec1[i]);
}
printf("Enter the elements of the second vector: ");
for (int i = 0; i < N; i++) {
scanf("%d", &vec2[i]);
}
int result = dotProduct(vec1, vec2);
printf("The dot product of the two vectors is: %d\n", result);
return 0;
}
分治法求数组中相差最小的两个元素(最接近数)的差
给定一个整数数组,编写一个程序来找到数组中相差最小的两个元素,并计算它们之间的差值。
#include<stdio.h>
#include<stdlib.h>
#include <limits.h>
//比较函数,用于qsort排序
int compare(const void*a,const void*b){
return(*(int*)a-*(int*)b);
}
//求两个数的差
int findMinDiff(int arr[],int n){
if(n<2){
return -1;//数组元素个数小于2,无法求解
}
//先对数组进行排序
qsort(arr,n,sizeof(int),compare);
//初始化最小差值可能为最大值
int minDiff=INT_MAX;
//求相邻两个元素之差的最小值
for(int i=1;i<n;i++){
if(arr[i]-arr[i-1]<minDiff){
minDiff=arr[i]-arr[i-1];
}
}
return minDiff;
}
int main(){
int n;
printf("Enter the number of elements in the array:");
scanf("%d",&n);
int arr[n];
printf("Enter the elements of the array:");
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
}
int result=findMinDiff(arr,n);
if(result==-1){
printf("Array must have at least 2 elements.\n");
}else{
printf("The minimum difference between two elements is:%d\n",result);
}
return 0;
}
分治法对任意的n值构造相应的格雷码
格雷码是一个长度为2n的序列,序列中无相同元素,且每个元素都是长度为n的二进制位串,相邻元素恰好只有1位不同。例如长度为23的格雷码为(000,001,011,010,110,111,101,100)。设计分治算法对任意的n值构造相应的格雷码。
#include <math.h>
#include <stdio.h>
int a[10000][10000];
//求num个n位Gray码
void GrayCode(int n, int num);
int main() {
int n; //输入Gray码位数n
scanf("%d", &n) ;
//n位Gray码的个数num
int num = (int)pow(2.0, n);
//求num个n位Gray码
GrayCode(n, num);
//输出num个n位Gray码
//为了方便运算,Gray码的矩阵从左上角开始构建,最高位在最右边,输出时每个Gray码从右往左输出
printf("Gray code sequence for n=%d\n",n);
for (int i = 0; i < num; ++i) {
for (int j = n - 1; j >= 0; --j) {
printf("%d", a[i][j]);
}
printf("\n");
}
return 0;
}
void GrayCode(int n, int num) {
//分治到只有1位Gray码的情况
if (n == 1) {
a[0][0] = 0;
a[1][0] = 1;
return;
}
//将求解n位Gray码的问题划分成求解n-1位Gray码的问题
GrayCode(n - 1, num / 2);
//n位Gray码的前半部分最高位置0,其余位不变
for (int i = 0; i < num / 2; ++i) {
a[i][n - 1] = 0;
}
//n位Gray码的后半部分最高位置1,其余位由n-1位Gray码翻转而来
for (int i = num / 2; i < num; ++i) {
a[i][n - 1] = 1;
for (int j = 0; j < n - 1; ++j) {
a[i][j] = a[num - i - 1][j];
}
}
}
使用分治法解决铺地毯问题
某个房间的地面被分割成一个个方格,每个方格被编号为 (x, y),其中 x 和 y 分别表示该方格的横纵坐标。现在有一些地毯需要铺在这个房间的地面上,每块地毯被描述为一个矩形,左下角坐标为 (x1, y1),右上角坐标为 (x2, y2)。如果一块地毯覆盖了一个方格,那么该方格就会被视为被覆盖。请设计一个算法,利用分治法判断给定的一个点 (x, y) 是否被地毯覆盖。
1.将地毯问题划分为多个子问题,每个子问题为判断点 (x, y) 是否被一个地毯覆盖。
2.对于每块地毯,判断点 (x, y) 是否位于其覆盖范围内。
//请在此处开始编写你的代码
#include <stdio.h>
// 定义地毯结构体
struct Carpet {
int x1, y1; // 左下角坐标
int x2, y2; // 右上角坐标
};
// 判断点是否在矩形范围内
int isInside(struct Carpet c, int x, int y) {
return (x >= c.x1 && x <= c.x2 && y >= c.y1 && y <= c.y2);
}
// 判断给定点是否被地毯覆盖
int isCovered(struct Carpet carpets[], int n, int x, int y) {
// 遍历每块地毯
for (int i = 0; i < n; i++) {
// 如果点在当前地毯的范围内,则返回当前地毯的编号
if (isInside(carpets[i], x, y)) {
return i;
}
}
// 如果点不被任何地毯覆盖,则返回-1
return -1;
}
int main() {
// 地毯数量
int n;
printf("Enter the number of carpets: ");
scanf("%d", &n);
// 输入每块地毯的信息
struct Carpet carpets[n];
for (int i = 0; i < n; i++) {
printf("Enter the coordinates of carpet %d (x1 y1 x2 y2): ", i + 1);
scanf("%d %d %d %d", &carpets[i].x1, &carpets[i].y1, &carpets[i].x2, &carpets[i].y2);
}
// 输入需要判断的点的坐标
int x, y;
printf("Enter the coordinates of the point (x y): ");
scanf("%d %d", &x, &y);
// 判断给定点是否被地毯覆盖
int covered = isCovered(carpets, n, x, y);
if (covered != -1) {
printf("The point (%d, %d) is covered by carpet %d.\n", x, y, covered + 1);
} else {
printf("The point (%d, %d) is not covered by any carpet.\n", x, y);
}
return 0;
}
使用减治法找数组中第K大元素
给定一个包含不同整数的无序数组,以及一个整数k。请设计一个算法,利用减治法找出数组中第k大的元素。
#include <stdio.h>
int partition(int arr[], int low, int high) {
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] > pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}
int quickSelect(int arr[], int low, int high, int k) {
if (low <= high) {
int pivot = partition(arr, low, high);
if (pivot == k - 1) {
return arr[pivot];
} else if (pivot < k - 1) {
return quickSelect(arr, pivot + 1, high, k);
} else {
return quickSelect(arr, low, pivot - 1, k);
}
}
return -1; // Error case
}
int main() {
int arr[] = {3, 9, 4, 5, 1, 8, 2, 7};
int n = sizeof(arr) / sizeof(arr[0]);
int k = 2; // Find the 2nd largest element
int result = quickSelect(arr, 0, n - 1, k);
if (result != -1) {
printf("The %d-th largest element is: %d\n", k, result);
} else {
printf("Invalid input\n");
}
return 0;
}
使用减治法求斐波那契数列的第n项
给定斐波那契数列的定义F(0)=0,F(1)=1,对于n>=2,F(n)=F(n-1)+F(n-2).请设计一个算法,利用减治法求解斐波那契数列的第n项
#include <stdio.h>
int F(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else if (n >= 2) {
return F(n - 1) + F(n - 2);
}
}
int main() {
int n;
scanf("%d", &n);
int a = F(n);
printf("The %d-th Fibonacci number is:%d\n", n, a);
return 0;
}
使用减治法找到整数数组元素之和
使用减治法找到整数数组元素之和
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int a[n];
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
int sum = 0;
for (int i = 0; i < n; i++) {
sum += a[i];
}
printf("%d", sum);
return 0;
}
求点到线段所在直线垂线的垂足
编写一段C语言算法,要求点到线段所在直线垂线的垂足
要计算一个点到线段所在直线的垂足,我们可以使用向量运算。首先,我们计算线段两个端点构成的向量,然后计算点到线段一个端点的向量。通过这两个向量,我们可以得到垂线的方向向量(即这两个向量的叉积)。然后,我们可以利用点积来计算垂足的位置。
//请在此处开始编写你的代码
#include <stdio.h>
#include <math.h>
typedef struct {
double x;
double y;
} Point;
Point perpendicularFoot(Point A, Point B, Point P) {
double ABx = B.x - A.x;
double ABy = B.y - A.y;
double APx = P.x - A.x;
double APy = P.y - A.y;
// 计算点A到点P的向量与线段AB的向量的点积
double dot = ABx * APx + ABy * APy;
// 计算线段AB的向量的模长的平方
double ABsq = ABx * ABx + ABy * ABy;
// 防止除以0的情况
if (fabs(ABsq) < 1e-9) {
return A; // 如果AB几乎为0,那么垂足就是A
}
// 计算参数t,表示点P到垂足的距离与点A到垂足的距离的比例
double t = dot / ABsq;
// 计算垂足的坐标
Point foot;
foot.x = A.x + t * ABx;
foot.y = A.y + t * ABy;
return foot;
}
int main() {
Point A, B, P;
printf("请输入点A的坐标(x y):");
scanf("%lf %lf", &A.x, &A.y);
printf("请输入点B的坐标(x y):");
scanf("%lf %lf", &B.x, &B.y);
printf("请输入点P的坐标(x y):");
scanf("%lf %lf", &P.x, &P.y);
Point foot = perpendicularFoot(A, B, P);
printf("垂足的坐标为: (%f, %f)\n", foot.x, foot.y);
return 0;
}
求矢量夹角
请编写一段C程序代码,要求计算两矢量之间的夹角
计算流程如下:
由点乘求夹角,再判断正负向量点乘求夹角:
a * b= |a| * |b| * cos<a,b>=a.x * b.x + a.y* b.y
所以<a,b> = acos((a * b)/ ( |a| * |b|) );
结果为正值,需要判定正负,来确定角方向;
由向量叉乘判断正负:
a X b = |a| * |b| * sin<a,b>=a.x * b.y - a.y * b.x;
如果aXb < 0,那么 <a,b> = -<a,b>
//请在此处开始编写你的代码
#include <stdio.h>
#include <math.h>
typedef struct {
double x;
double y;
} Vector;
double dotProduct(Vector v1, Vector v2) {
return v1.x * v2.x + v1.y * v2.y;
}
double magnitude(Vector v) {
return sqrt(v.x * v.x + v.y * v.y);
}
double angleBetweenVectors(Vector v1, Vector v2) {
double dot = dotProduct(v1, v2);
double mag1 = magnitude(v1);
double mag2 = magnitude(v2);
// 计算夹角的余弦值
double cosTheta = dot / (mag1 * mag2);
// 计算夹角(弧度)
double thetaRad = acos(cosTheta);
// 将弧度转换为度
double thetaDeg = thetaRad * (180.0 / M_PI);
return thetaDeg;
}
int main() {
Vector v1, v2;
printf("请输入第一个矢量的x坐标和y坐标(用空格分隔):");
scanf("%lf %lf", &v1.x, &v1.y);
printf("请输入第二个矢量的x坐标和y坐标(用空格分隔):");
scanf("%lf %lf", &v2.x, &v2.y);
double angle = angleBetweenVectors(v1, v2);
printf("两个矢量的夹角为:%.2lf度\n", angle);
return 0;
}
求一点饶某点旋转后的坐标
要求编写一段C语言程序,实现 A 点绕 B 点旋转 n 角度后的 A 点坐标
//请在此处开始编写你的代码
#include <stdio.h>
#include <math.h>
// 定义一个结构体来存储点的坐标
typedef struct {
double x;
double y;
} Point;
// 函数用于将角度转换为弧度
double degreesToRadians(double degrees) {
return degrees * M_PI / 180.0;
}
// 函数用于计算点绕原点的旋转
Point rotateAroundOrigin(Point point, double angleRadians) {
double cosTheta = cos(angleRadians);
double sinTheta = sin(angleRadians);
Point rotatedPoint;
rotatedPoint.x = point.x * cosTheta - point.y * sinTheta;
rotatedPoint.y = point.x * sinTheta + point.y * cosTheta;
return rotatedPoint;
}
// 函数用于计算点绕任意点的旋转
Point rotateAroundPoint(Point point, Point center, double angleRadians) {
// 先将点平移到原点
Point shiftedPoint = { point.x - center.x, point.y - center.y };
// 绕原点旋转
Point rotatedPoint = rotateAroundOrigin(shiftedPoint, angleRadians);
// 将旋转后的点平移回原来的位置
rotatedPoint.x += center.x;
rotatedPoint.y += center.y;
return rotatedPoint;
}
int main() {
Point A, B;
double angleDegrees;
// 读取输入
scanf("%lf %lf", &A.x, &A.y);
scanf("%lf %lf", &B.x, &B.y);
scanf("%lf", &angleDegrees);
// 计算旋转后的坐标
double angleRadians = degreesToRadians(angleDegrees);
Point rotatedA = rotateAroundPoint(A, B, angleRadians);
// 输出结果
printf("旋转后的坐标是: (%.2f, %.2f)\n", rotatedA.x, rotatedA.y);
return 0;
}
判断点是否在线段上
请编写一段c语言代码,要求判断一个点是否在线段AB上(要求手动输入数据)
//请在此处开始编写你的代码
#include <stdio.h>
// 定义点的结构体
typedef struct {
int x;
int y;
} Point;
// 判断点P是否在线段AB上
int isOnSegment(Point A, Point B, Point P) {
// 计算向量AB和向量AP的叉积
int cross = (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x);
// 如果叉积为0且P在A和B之间,则点P在线段AB上
if (cross == 0 && (P.x >= A.x && P.x <= B.x) && (P.y >= A.y && P.y <= B.y)) {
return 1;
} else {
return 0;
}
}
int main() {
Point A, B, P;
// 输入线段端点A的坐标
scanf("%d %d", &A.x, &A.y);
// 输入线段端点B的坐标
scanf("%d %d", &B.x, &B.y);
// 输入要判断的点P的坐标
scanf("%d %d", &P.x, &P.y);
// 调用函数判断点P是否在线段AB上
if (isOnSegment(A, B, P)) {
printf("点P在线段AB上\n");
} else {
printf("点P不在线段AB上\n");
}
return 0;
}
矢量叉乘
矢量叉乘的计算主要基于叉乘的定义和性质。对于两个三维向量A和B,它们的叉乘结果是一个新的向量C,其方向垂直于A和B所在的平面,并且遵循右手螺旋定则。向量C的模长等于A和B构成的平行四边形的面积。
//请在此处开始编写你的代码
#include <stdio.h>
// 定义一个结构体来存储三维向量的分量
typedef struct {
double x;
double y;
double z;
} Vector3D;
// 函数用于计算两个三维向量的叉乘
Vector3D crossProduct(Vector3D A, Vector3D B) {
Vector3D C;
C.x = A.y * B.z - A.z * B.y;
C.y = A.z * B.x - A.x * B.z;
C.z = A.x * B.y - A.y * B.x;
return C;
}
int main() {
Vector3D A, B, C;
// 读取向量A的分量
scanf("%lf", &A.x);
scanf("%lf", &A.y);
scanf("%lf", &A.z);
// 读取向量B的分量
scanf("%lf", &B.x);
scanf("%lf", &B.y);
scanf("%lf", &B.z);
// 计算叉乘结果
C = crossProduct(A, B);
// 输出结果
printf("叉乘结果向量为:(%f,%f,%f)", C.x, C.y, C.z);
return 0;
}
判断平面两点是否重合
请编写一个算法,用以判断平面上的两点是否重合
//请在此处开始编写你的代码
#include <stdio.h>
int main() {
int x1, y1, x2, y2;
// 读取输入
scanf("%d", &x1);
scanf("%d", &y1);
scanf("%d", &x2);
scanf("%d", &y2);
// 判断两点是否重合
if (x1 == x2 && y1 == y2) {
printf("The two points are equal.\n");
} else {
printf("The two points are not equal.\n");
}
return 0;
}
计算平面两点距离
在平面上,两点之间的距离可以通过欧几里得距离公式来计算。对于两点 A(x1, y1) 和 B(x2, y2),它们之间的距离 d 可以用以下公式表示:
d = sqrt((x2 - x1)² + (y2 - y1)²)
#include <stdio.h>
#include <math.h>
int main() {
int x1, y1, x2, y2;
scanf("%d", &x1);
scanf("%d", &y1);
scanf("%d", &x2);
scanf("%d", &y2);
double d;
d = sqrt((x2 - x1) * (x2 - x1) * 1.0 + (y2 - y1) * (y2 - y1) * 1.0);
printf("The distance between the two points is:%lf", d);
return 0;
}
汉诺塔
//请在此处开始编写你的代码
#include <stdio.h>
// 函数原型声明
void hanoi(int n, char source, char auxiliary, char target);
int main() {
int n;
// 读取输入
scanf("%d", &n);
// 调用汉诺塔函数
hanoi(n, 'A', 'B', 'C');
return 0;
}
// hanoi函数实现
void hanoi(int n, char source, char auxiliary, char target) {
if (n == 1) {
// 只有一个圆盘,直接移动到目标杆
printf("Move disk %d from %c to %c\n", n, source, target);
} else {
// 递归步骤1:将n-1个圆盘从source移动到auxiliary
hanoi(n - 1, source, target, auxiliary);
// 打印移动n的圆盘
printf("Move disk %d from %c to %c\n", n, source, target);
// 递归步骤2:将n-1个圆盘从auxiliary移动到target
hanoi(n - 1, auxiliary, source, target);
}
}
对链表排序
创建一个无序链表,使用算法对其排序,使其变为升序链表
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
typedef struct ListNode {
int val; struct ListNode *next;
} ListNode;
// 创建新节点
ListNode *createNode(int val) {
ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
if (!newNode) {
perror("Memory allocation failed");
exit(EXIT_FAILURE);
}
newNode->val = val;
newNode->next = NULL;
return newNode;
}
// 插入节点到链表尾部
void insertNode(ListNode **head, int val) {
ListNode *newNode = createNode(val);
if (*head == NULL) {
*head = newNode;
} else {
ListNode *temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
// 打印链表
void printList(ListNode *head) {
ListNode *temp = head;
while (temp != NULL) {
printf("%d ", temp->val);
temp = temp->next;
}
printf("\n");
}
// 排序链表
void sortList(ListNode **head) {
if (head == NULL || *head == NULL) {
return;
}
ListNode *sorted = NULL;
ListNode *current = *head;
ListNode *temp = NULL;
// 遍历链表,将每个节点插入到排序链表中
while (current != NULL) {
// 先暂时从原链表中移除当前节点
temp = current->next;
current->next = NULL;
// 如果排序链表为空或者当前节点值小于排序链表最后一个节点的值,则直接插入
if (sorted == NULL || current->val < sorted->val) {
current->next = sorted;
sorted = current;
} else {
ListNode *cur = sorted;
while (cur->next != NULL && cur->next->val < current->val) {
cur = cur->next;
}
current->next = cur->next;
cur->next = current;
}
// 继续处理下一个节点
current = temp;
}
// 更新头指针指向排序后的链表
*head = sorted;
}
int main() {
ListNode *head = NULL;
int val;
// 读取输入并创建链表
while (scanf("%d", &val) && val != -1) {
insertNode(&head, val);
}
// 打印原始链表
printf("原始链表: ");
printList(head);
// 排序链表
sortList(&head);
// 打印排序后的链表
printf("排序后的链表: ");
printList(head);
// 释放链表内存
ListNode *temp;
while (head != NULL) {
temp = head;
head = head->next;
free(temp);
}
return 0;
}
合并两个升序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的
//请在此处开始编写你的代码
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
Node *createNode(int data) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
void insertNode(Node **head, int data) {
Node *newNode = createNode(data);
if (*head == NULL || (*head)->data >= newNode->data) {
newNode->next = *head;
*head = newNode;
} else {
Node *current = *head;
while (current->next != NULL && current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
current->next = newNode;
}
}
void printList(Node *head) {
while (head != NULL) {
printf("%d ", head->data);
head = head->next;
}
printf("\n");
}
Node *mergeLists(Node *first, Node *second) {
Node dummy;
dummy.next = NULL;
Node *tail = &dummy;
while (first != NULL && second != NULL) {
if (first->data < second->data) {
tail->next = first;
first = first->next;
} else {
tail->next = second;
second = second->next;
}
tail = tail->next;
}
tail->next = first ? first : second;
return dummy.next;
}
int main() {
Node *list1 = NULL;
Node *list2 = NULL;
int data;
// 读取第一个链表的值
printf("输入第一个有序链表的值(以-1结束):\n");
scanf("%d", &data);
while (data != -1) {
insertNode(&list1, data);
scanf("%d", &data);
}
// 读取第二个链表的值
printf("输入第二个有序链表的值(以-1结束):\n");
scanf("%d", &data);
while (data != -1) {
insertNode(&list2, data);
scanf("%d", &data);
}
// 打印原始链表
printf("List 1: ");
printList(list1);
printf("List 2: ");
printList(list2);
// 合并链表
Node *mergedList = mergeLists(list1, list2);
// 打印合并后的链表
printf("Merged List: ");
printList(mergedList);
// 释放链表内存
while (mergedList != NULL) {
Node *temp = mergedList;
mergedList = mergedList->next;
free(temp);
}
return 0;
}
二分搜索
二分搜索,也称折半搜索或对数搜索,是一种在有序数组中查找某一特定元素的搜索算法。该算法的基本思想是每次都将搜索范围缩小一半,直到找到目标元素或搜索区间为空为止。
//请在此处开始编写你的代码
#include <stdio.h>
// 二分搜索函数
int binarySearch(int arr[], int l, int r, int x) {
while (l <= r) {
int m = l + (r - l) / 2;
// 检查m是否是x的索引
if (arr[m] == x) {
return m;
}
// 如果x更大,我们对右侧子数组进行搜索
if (arr[m] < x) {
l = m + 1;
}
// 如果x更小,我们对左侧子数组进行搜索
else {
r = m - 1;
}
}
// 如果我们没有找到x,返回-1
return -1;
}
int main() {
int n, target, result;
scanf("%d", &n); // 读取数列的元素个数
int arr[n];
scanf("%d", &arr[0]); // 读取第一个元素并开始构建数组
for (int i = 1; i < n; i++) {
scanf("%d", &arr[i]);
}
scanf("%d", &target); // 读取要搜索的目标值
// 调用二分搜索函数
result = binarySearch(arr, 0, n - 1, target);
// 输出结果
if (result != -1) {
printf("元素 %d 在数列中的索引为 %d\n", target, result);
} else {
printf("元素 %d 不在数列中\n", target);
}
return 0;
}
快速排序
//请在此处开始编写你的代码
#include <stdio.h>
// 定义一个结构体来存储快速排序的索引
typedef struct {
int low;
int high;
} Index;
// 交换两个元素的值
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 快速排序的分区函数
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // 选择最右侧元素作为基准
int i = low - 1; // i指针用于记录小于基准的元素的最右位置
for (int j = low; j < high; j++) {
// 如果当前元素小于或等于基准
if (arr[j] <= pivot) {
i++; // i指针右移
swap(&arr[i], &arr[j]);
}
}
// 将基准元素放到正确的位置
swap(&arr[i + 1], &arr[high]);
return i + 1;
}
// 快速排序的递归函数
void quickSort(int arr[], int low, int high) {
if (low < high) {
// 分区并得到基准的索引
int pivotIndex = partition(arr, low, high);
// 对基准左边的子序列进行快速排序
quickSort(arr, low, pivotIndex - 1);
// 对基准右边的子序列进行快速排序
quickSort(arr, pivotIndex + 1, high);
}
}
// 主函数
int main() {
int n, i;
// 读取数列长度
scanf("%d", &n);
int arr[n];
// 读取数列
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// 执行快速排序
quickSort(arr, 0, n - 1);
// 输出排序后的数组
printf("Sorted array:\n");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
循环赛日程表问题
循环赛日程表问题,指的是在给定参赛选手数量的情况下,如何安排每两名选手之间的比赛,使得每名选手在相邻的两场比赛中都不会遇到相同的对手。这个问题通常可以通过使用分治策略来解决,特别是当参赛人数数量为偶数时,可以方便地利用分治策略来构造循环赛日程表。
//请在此处开始编写你的代码
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
//分治递归,mStart是分治区域的起始的纵坐标,mEnd是分治区域结束的纵坐标
//nStart是分治区域的起始的横坐标,nEnd是分治区域的结束的横坐标
void arrange(int** a, int mStart, int mEnd, int nStart, int nEnd)
{ //只有一个参赛选手,只能自己与自己比 if (mStart == mEnd && nStart == nEnd)
if(mStart==mEnd&&nStart==nEnd)
{
a[mStart][nStart] = nStart;
return;
}
//有两个选手,矩阵对角线相等
if (mStart + 1 == mEnd && nStart + 1 == nEnd)
{ //主对角线相等
a[mStart][nStart] = nStart;
a[mEnd][nEnd] = nStart;
//逆对角线相等
a[mStart][nEnd] = nEnd;
a[mEnd][nStart] = nEnd;
return;
}
int mMid = (mStart + mEnd) / 2;
int nMid = (nStart + nEnd) / 2;
arrange(a, mStart, mMid, nStart, nMid);//左上角分块矩阵
arrange(a, mStart, mMid, nMid + 1, nEnd);//右上角分块矩阵
//将左上角分块矩阵复制到右下角
for (int i = mMid + 1; i <= mEnd; i++)
{
for (int j = nMid + 1; j <= nEnd; j++)
{
a[i][j] = a[i - mMid][j - nMid];
}
}
//将右上角分块矩阵复制到左下角
for (int i = mMid+1; i <= mEnd; i++)
{
for (int j = nStart; j <= nMid; j++)
{
a[i][j] = a[i - (mMid-mStart+1)][j + (nMid - nStart+1)];//mMid-mStart+1是左下角纵坐标到上半矩阵对应纵坐标的距离,nMid - nStart+1同理
}
}
}
//打印矩阵
void printMatrix(int** a, int m, int n)
{ printf("参赛\n选手\t");
for (int i = 2; i < n; i++)
{ printf("第%d天\t", i - 1); }
printf("\n");
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
printf("%d\t", a[i][j]);
}
printf("\n");
}
}
int main()
{ int m = 0;//参赛选手人数
printf("请输入参赛选手的个数:\n");
scanf("%d", &m);
if ((m & (m-1)) != 0)//判断2的n次方的经典条件(m & (m-1))的结果为0就是,注意加括号,符号优先级要注意
{ printf("参赛选手必须为2的n次方!\n");
return 0;
}
int** matrix = (int**)malloc((m+1) * sizeof(int*));
for (int i = 0; i < (m+1); i++)
{ matrix[i] = (int*)malloc((m + 1) * sizeof(int));
memset(matrix[i], 0, (m + 1) * sizeof(int));//将二维数组每一行置为0
}
arrange(matrix, 1, m, 1, m);
printMatrix(matrix, m+1, m+1);
}
线性时间选择选k小值
线性时间选择算法(Linear Time Selection Algorithm)是一种能在O(n)时间复杂度内从无序列表中找出第k小(或第k大)元素的算法。一个著名的线性时间选择算法是快速选择算法(QuickSelect),它是快速排序算法的一个变种。
//请在此处开始编写你的代码
#include <stdio.h>
#include <stdlib.h>
// 交换两个元素的值
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 选择一个随机的基准值
int selectPivot(int *arr, int low, int high) {
int idx = low + rand() % (high - low);
swap(&arr[high], &arr[idx]);
return arr[high];
}
// 快速选择算法的分区函数
int partition(int *arr, int low, int high) {
int pivot = selectPivot(arr, low, high);
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return i + 1;
}
// 快速选择算法
int quickSelect(int *arr, int low, int high, int k) {
if (low == high)
return arr[low];
int pivotIndex = partition(arr, low, high);
if (k == pivotIndex) {
return arr[k];
} else if (k < pivotIndex) {
return quickSelect(arr, low, pivotIndex - 1, k);
} else {
return quickSelect(arr, pivotIndex + 1, high, k);
}
}
int main() {
int n, k, i;
scanf("%d", &n); // 读取数列长度
int arr[n];
scanf("%d", &arr[0]); // 读取第一个元素
for (i = 1; i < n; i++) {
scanf("%d", &arr[i]);
}
scanf("%d", &k); // 读取k值
// 计算第k小的元素的索引(从1开始)
int kthSmallest = quickSelect(arr, 0, n - 1, k - 1);
printf("The %dth smallest element is %d\n", k, kthSmallest);
return 0;
}
归并排序
#include<stdio.h>
//请在此处开始编写你的代码
#include<bits/stdc++.h>
using namespace std;
void Mergearray(int a[],int first,int mid,int last,int temp[]){
int i=first,j=mid+1;
int m=mid,n=last;
int k=0;
while(i<=m&&j<=n)
{
if(a[i]<a[j])
temp[k++]=a[i++];
else
temp[k++]=a[j++];
}
while(i<=m)
temp[k++]=a[i++];
while(j<=n)
temp[k++]=a[j++];
for(i=0;i<k;i++)
a[first+i]=temp[i];
}
void Mergesort(int a[],int first,int last,int temp[]) //将两个任意数组合并排序
{
if(first<last)
{
int mid=(first+last)/2;
Mergesort(a,first,mid,temp); //左边有序
Mergesort(a,mid+1,last,temp); //右边有序
Mergearray(a,first,mid,last,temp); //再将两个有序数组合并
}
}
bool MergeSort(int a[], int n)
{
int *p = new int[n]; //分配一个有n个int型元素的数组所占空间,并将该数组的第一个元素的地址赋给int *型指针p。
if (p == NULL)
return false;
Mergesort(a, 0, n - 1, p);
delete[] p;
return true;
}
int main()
{
int a[1000];
int n;
printf("请输入数的个数:\n");
scanf("%d",&n);
printf("请输入要排序的数列:\n");
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
MergeSort(a,n);
printf("排序结果为:");
for(int i=0;i<n;i++)
printf(" %d ",a[i]);
}
大整数乘法
背景:在科学计算中,无法计算非常大的整数,于是就有大整数乘法问题。(int存放4字节,float…已有的数据类型数据范围有限),硬件无法实现,只能靠软件(代码)实现了。
要求:求两个不超过200位的非负整数的积
#include<stdio.h>
#include<string.h>
#define N 100
int main()
{
int i, j, L[N];
char m[N], n[N];
scanf("%s %s", m, n);
int len1 = strlen(m);
int len2 = strlen(n);
memset(L, 0, sizeof(L));
for(i = 0; i < len1; i++)
for(j = 0; j < len2; j++)
L[i+j] += (m[len1 - i - 1] - '0') * (n[len2 - j - 1] - '0');
for(i = 0; i < len1 + len2; i++)
if(L[i] >= 10)
{
L[i+1] += L[i] / 10;
L[i] %= 10;
}
while(L[i] == 0)
i--;
while(i >= 0)
printf("%d", L[i--]);
return 0;
}
选k小数
给定一个长度为 n的整数数列,以及一个整数 k,请用快速选择算法求出数列从小到大排序后的第 k个数。
//请在此处开始编写你的代码
#include <stdio.h>
#include <stdlib.h>
// 随机选择枢纽元的索引
int randomPivot(int low, int high) {
return low + rand() % (high - low + 1);
}
// 交换两个元素的值
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 快速选择算法的分区函数
int partition(int arr[], int low, int high) {
int pivotIndex = randomPivot(low, high);
int pivotValue = arr[pivotIndex];
swap(&arr[pivotIndex], &arr[high]); // 将枢纽元放到数列的末尾
int i = low;
for (int j = low; j < high; j++) {
if (arr[j] < pivotValue) {
swap(&arr[i], &arr[j]);
i++;
}
}
swap(&arr[i], &arr[high]); // 将枢纽元放到正确的位置
return i;
}
// 快速选择算法
int quickSelect(int arr[], int low, int high, int k) {
if (low == high) {
return arr[low];
}
int pivotIndex = partition(arr, low, high);
if (k == pivotIndex) {
return arr[k];
} else if (k < pivotIndex) {
return quickSelect(arr, low, pivotIndex - 1, k);
} else {
return quickSelect(arr, pivotIndex + 1, high, k);
}
}
int main() {
int n, k, i;
scanf("%d %d", &n, &k); // 读取数列长度和k值
int arr[n];
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]); // 读取数列
}
// 设置随机种子
srand((unsigned) time(NULL));
// 调用快速选择算法,查找第k小的数
int kthElement = quickSelect(arr, 0, n - 1, k - 1);
printf("%d\n", kthElement);
return 0;
}
查找一个整数数组中第二大数
实现一个函数,查找一个整数数组中第二大数
//请在此处开始编写你的代码
#include <stdio.h>
#include <limits.h>
int findSecondMax(int arr[], int n) {
int max = INT_MIN, secondMax = INT_MIN;
for (int i = 0; i < n; i++) {
if (arr[i] > max) {
// 更新第二大值,然后找到新的最大值
secondMax = max;
max = arr[i];
} else if (arr[i] > secondMax && arr[i] != max) {
// 更新第二大值
secondMax = arr[i];
}
}
return secondMax;
}
int main() {
int n, i;
scanf("%d", &n); // 读取数组长度
int arr[n];
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]); // 读取数组元素
}
// 调用函数查找第二大的数
int secondMax = findSecondMax(arr, n);
printf("the second_max is: %d\n", secondMax);
return 0;
}
十个数选最小并返回位置
编程题
题目描述:
从键盘输入10个整数,找出其中的最小数及其位置
#include <stdio.h>
#include <math.h>
int min(int a[]) {
int x = a[0];
for (int i = 1; i < 10; i++) {
if (a[i] < x) {
x = a[i];
}
}
return x;
}
int main() {
int a[10];
for (int i = 0; i < 10; i++) {
scanf("%d", &a[i]);
}
int x = min(a);
for (int i = 0; i < 10; i++) {
if (a[i] == x) {
printf("最小数为:%d 位置为:%d", x, i);
}
}
return 0;
}
在二维有序矩阵中查找目标值的出现次数
给定一个 m x n 的二维有序矩阵,矩阵中可能包含重复元素,以及一个目标值 target,设计一个算法来计算矩阵中目标值的出现次数。矩阵具有以下特性:
每行的整数从左到右升序排列。
每列的整数从上到下升序排列。
#include <stdio.h>
#include <stdlib.h>
int searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target) {
int count = 0;
int row = 0;
int col = *matrixColSize - 1;
while (row < matrixSize && col >= 0) {
if (matrix[row][col] == target) {
count++;
col--;
}
else if (matrix[row][col] > target) {
col--;
}
else {
row++;
}
}
return count;
}
int main() {
int m, n;
printf("请输入矩阵的行数和列数:");
scanf("%d %d", &m, &n);
int** matrix = (int**)malloc(sizeof(int*) * m);
for (int i = 0; i < m; i++) {
matrix[i] = (int*)malloc(sizeof(int) * n);
}
printf("请输入有序矩阵的元素(按行输入):\n");
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &matrix[i][j]);
}
}
int target;
printf("请输入目标值:");
scanf("%d", &target);
int result = searchMatrix(matrix, m, &n, target);
printf("目标值 %d 出现的次数是:%d\n", target, result);
for (int i = 0; i < m; i++) {
free(matrix[i]);
}
free(matrix);
return 0;
}
在有序链表中的插入值
给定一个升序排列的有序链表和一个目标值,设计一个算法来找到目标值在有序链表中的插入位置,即将目标值插入到链表中后仍然保持有序。
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int val;
struct ListNode* next;
} ListNode;
int searchInsert(ListNode* head, int target) {
int index = 0;
while (head != NULL && head->val < target) {
head = head->next;
index++;
}
return index;
}
ListNode* createNode(int val) {
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
if (newNode == NULL) {
printf("内存分配失败\n");
exit(1);
}
newNode->val = val;
newNode->next = NULL;
return newNode;
}
ListNode* createLinkedList() {
int n, val;
printf("请输入链表的长度:");
scanf("%d", &n);
ListNode* head = NULL;
ListNode* temp = NULL;
printf("请输入链表的元素(升序排列):");
for (int i = 0; i < n; i++) {
scanf("%d", &val);
ListNode* newNode = createNode(val);
if (head == NULL) {
head = newNode;
temp = head;
}
else {
temp->next = newNode;
temp = temp->next;
}
}
return head;
}
void freeLinkedList(ListNode* head) {
ListNode* temp;
while (head != NULL) {
temp = head;
head = head->next;
free(temp);
}
}
int main() {
ListNode* head = createLinkedList();
int target;
printf("请输入目标值:");
scanf("%d", &target);
int index = searchInsert(head, target);
printf("目标值 %d 的插入位置是:%d\n", target, index);
freeLinkedList(head);
return 0;
}
在有序链表中查找最接近目标值的节点值
给定一个升序排列的有序链表和一个目标值,设计一个算法来找到链表中最接近目标值的节点值。
//请在此处开始编写你的代码
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
// 创建新链表节点
ListNode *createNode(int data) {
ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->val = data;
newNode->next = NULL;
return newNode;
}
// 给定头节点,创建一个升序列表
ListNode *createSortedList(int *arr, int n) {
ListNode *head = NULL, *tail = NULL;
for (int i = 0; i < n; i++) {
tail = createNode(arr[i]);
if (!head) {
head = tail;
} else {
tail->next = head;
head = tail;
}
}
return head;
}
// 找到链表中最接近目标值的节点值
int findClosestValue(ListNode *head, int target) {
int closest = head->val;
ListNode *current = head;
while (current != NULL) {
if (abs(closest - target) > abs(current->val - target)) {
closest = current->val;
}
current = current->next;
}
return closest;
}
int main() {
int n, target, i;
scanf("%d", &n); // 读取链表的长度
int *arr = (int *)malloc(n * sizeof(int));
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]); // 读取链表元素
}
scanf("%d", &target); // 读取目标值
// 创建升序列表
ListNode *head = createSortedList(arr, n);
// 找到最接近目标值的节点值
int closestValue = findClosestValue(head, target);
// 输出结果
printf("链表中最接近目标值 %d 的节点值是:%d\n", target, closestValue);
// 释放链表内存
while (head != NULL) {
ListNode *temp = head;
head = head->next;
free(temp);
}
free(arr);
return 0;
}
在有序链表中查找目标值的出现次数
给定一个升序排列的有序链表和一个目标值,设计一个算法来计算链表中目标值的出现次数。
//请在此处开始编写你的代码
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
// 创建新链表节点
ListNode *createNode(int data) {
ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->val = data;
newNode->next = NULL;
return newNode;
}
// 给定头节点,将数组元素插入到链表中
void insertToList(ListNode **head, int data) {
ListNode *newNode = createNode(data);
if (*head == NULL || (*head)->val >= data) {
newNode->next = *head;
*head = newNode;
} else {
ListNode *current = *head;
while (current->next != NULL && current->next->val < data) {
current = current->next;
}
newNode->next = current->next;
current->next = newNode;
}
}
// 计算链表中目标值的出现次数
int countOccurrences(ListNode *head, int target) {
int count = 0;
ListNode *current = head;
while (current != NULL) {
if (current->val == target) {
count++;
// 继续遍历直到数值改变,以便计算连续出现的次数
while (current->next != NULL && current->next->val == target) {
current = current->next;
count++;
}
}
current = current->next;
}
return count;
}
int main() {
int n, target, i;
scanf("%d", &n); // 读取链表的长度
ListNode *head = NULL;
for (i = 0; i < n; i++) {
int value;
scanf("%d", &value);
insertToList(&head, value);
}
scanf("%d", &target); // 读取目标值
// 计算目标值的出现次数
int count = countOccurrences(head, target);
// 输出结果
printf("目标值 %d 的出现次数是:%d\n", target, count);
// 释放链表内存
while (head != NULL) {
ListNode *temp = head;
head = head->next;
free(temp);
}
return 0;
}
在有序链表中查找目标值的最小索引
给定一个升序排列的有序链表和一个目标值,设计一个算法来查找链表中第一次出现目标值的位置。如果目标值存在于链表中,则返回第一次出现的位置索引(从0开始),否则返回-1。
//请在此处开始编写你的代码
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
// 创建新链表节点
ListNode *createNode(int data) {
ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->val = data;
newNode->next = NULL;
return newNode;
}
// 给定头节点,将数组元素插入到链表中
void insertToList(ListNode **head, int *arr, int index) {
ListNode *newNode = createNode(arr[index]);
if (*head == NULL || (*head)->val > newNode->val) {
newNode->next = *head;
*head = newNode;
} else {
ListNode *current = *head;
while (current->next != NULL && current->next->val < newNode->val) {
current = current->next;
}
newNode->next = current->next;
current->next = newNode;
}
}
// 查找链表中目标值的第一次出现位置
int findFirstOccurrence(ListNode *head, int target) {
int index = 0;
ListNode *current = head;
while (current != NULL) {
if (current->val == target) {
return index;
}
index++;
current = current->next;
}
return -1; // 如果没有找到目标值,则返回-1
}
int main() {
int n, target, i;
scanf("%d", &n); // 读取链表的长度
int *arr = (int *)malloc(n * sizeof(int));
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]); // 读取链表元素
}
scanf("%d", &target); // 读取目标值
// 创建升序列表
ListNode *head = NULL;
for (i = 0; i < n; i++) {
insertToList(&head, arr, i);
}
// 查找目标值的第一次出现位置
int firstOccurrence = findFirstOccurrence(head, target);
// 输出结果
if (firstOccurrence != -1) {
printf("目标值 %d 的最小索引是:%d\n", target, firstOccurrence);
} else {
printf("目标值 %d 不存在于链表中\n", target);
}
// 释放链表和数组内存
while (head != NULL) {
ListNode *temp = head;
head = head->next;
free(temp);
}
free(arr);
return 0;
}
查找链表中的最大值
给定一个有序链表,设计一个算法来查找链表中的最大值。
//请在此处开始编写你的代码
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
// 创建新链表节点
ListNode *createNode(int data) {
ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->val = data;
newNode->next = NULL;
return newNode;
}
// 给定头节点,将数组元素插入到链表中
void insertToList(ListNode **head, int data) {
ListNode *newNode = createNode(data);
if (*head == NULL || (*head)->val < data) {
newNode->next = *head;
*head = newNode;
} else {
ListNode *current = *head;
while (current->next != NULL && current->next->val > data) {
current = current->next;
}
newNode->next = current->next;
current->next = newNode;
}
}
// 查找链表中的最大值
int findMaxValue(ListNode *head) {
ListNode *current = head;
int maxVal = current->val; // 假设第一个元素是最大值
while (current != NULL) {
if (current->val > maxVal) {
maxVal = current->val; // 找到更大的值,更新最大值
}
current = current->next;
}
return maxVal;
}
int main() {
int n, i;
scanf("%d", &n); // 读取链表的长度
ListNode *head = NULL;
for (i = 0; i < n; i++) {
int value;
scanf("%d", &value);
insertToList(&head, value);
}
// 查找最大值
int maxVal = findMaxValue(head);
// 输出结果
printf("链表中的最大值是:%d\n", maxVal);
// 释放链表内存
while (head != NULL) {
ListNode *temp = head;
head = head->next;
free(temp);
}
return 0;
}
查找链表中的目标值
给定一个有序链表,设计一个算法来查找链表中是否存在目标值 target。如果目标值存在,则返回目标值存在于链表中;否则,返回目标值不存在于链表中。
//请在此处开始编写你的代码
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
// 创建新链表节点
ListNode *createNode(int data) {
ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->val = data;
newNode->next = NULL;
return newNode;
}
// 给定头节点,将数组元素插入到链表中
void insertToList(ListNode **head, int *arr, int index) {
if (*head == NULL) {
*head = createNode(arr[index]);
} else {
ListNode *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = createNode(arr[index]);
}
}
// 查找链表中是否存在目标值
int existsTarget(ListNode *head, int target) {
ListNode *current = head;
while (current != NULL) {
if (current->val == target) {
return 1; // 目标值存在于链表中
}
current = current->next;
}
return 0; // 目标值不存在于链表中
}
int main() {
int n, target, i;
scanf("%d", &n); // 读取链表的长度
int *arr = (int *)malloc(n * sizeof(int));
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]); // 读取链表元素
}
scanf("%d", &target); // 读取目标值
// 创建链表
ListNode *head = NULL;
for (i = 0; i < n; i++) {
insertToList(&head, arr, i);
}
// 查找目标值是否存在
int exists = existsTarget(head, target);
// 输出结果
if (exists) {
printf("目标值存在于链表中。\n");
} else {
printf("目标值不存在于链表中。\n");
}
// 释放链表内存
while (head != NULL) {
ListNode *temp = head;
head = head->next;
free(temp);
}
free(arr);
return 0;
}
寻找无序数组中的局部最小值
给定一个无序的整数数组 nums,设计一个算法来找到数组中的一个局部最小值。局部最小值定义为比其相邻元素小的元素。
//请在此处开始编写你的代码
#include <stdio.h>
// 函数用于找到数组中的局部最小值
int findLocalMin(int arr[], int n) {
for (int i = 1; i < n - 1; i++) {
if (arr[i] < arr[i - 1] && arr[i] < arr[i + 1]) {
return i; // 返回局部最小值的索引
}
}
return -1; // 如果没有找到局部最小值,则返回-1
}
int main() {
int n, i;
scanf("%d", &n); // 读取数组的长度
int arr[n];
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]); // 读取数组元素
}
// 查找局部最小值的索引
int localMinIndex = findLocalMin(arr, n);
if (localMinIndex != -1) {
printf("数组中的局部最小值是:%d\n", arr[localMinIndex]);
} else {
printf("没有找到局部最小值。\n");
}
return 0;
}
寻找有序矩阵中的目标值
给定一个按行和列都按升序排列的 m x n 矩阵 matrix,以及一个目标值 target。如果目标值存在于矩阵中,则返回目标值存在于矩阵中;否则,返回目标值不存在于矩阵中。
#include<stdio.h>
#define ROWS 4
#define COLS 4
int searchMatrix(int matrix[ROWS][COLS],int target){
int row=0;
int col=COLS-1;
while(row<ROWS&&col>=0){
if(matrix[row][col]==target)
return 1;
else if(matrix[row][col]>target)
col--;
else
row++;
}
return 0;
}
int main(){
int matrix[ROWS][COLS];
int target;
printf("请输入%d x %d矩阵:\n",ROWS,COLS);
for(int i=0;i<ROWS;i++){
for(int j=0;j<COLS;j++){
scanf("%d",&matrix[i][j]);
}
}
printf("请输入目标值:\n");
scanf("%d",&target);
if(searchMatrix(matrix,target))
printf("目标值存在于矩阵中。\n");
else
printf("目标值不存在于矩阵中。\n");
return 0;
}
在旋转排序数组中查找最小值(减治)
整数数组
其中,整数数组表示旋转排序数组,假设数组中不存在重复元素,以空格分隔。
#include<stdio.h>
#include<stdlib.h>
int findMin(int arr[],int size){
if(size==1){
return arr[0];
}
int left=0,right=size-1;
while(left<right){
int mid=left+(right-left)/2;
if(arr[mid]>arr[right]){
left=mid+1;
}
else{
right=mid;
}
}
return arr[left];
}
int main(){
int size;
printf("请输入旋转排序数组的长度:\n");
scanf("%d",&size);
int*arr=(int*)malloc(size*sizeof(int));
if(arr==NULL){
printf("内存分配失败\n");
return 1;
}
printf("请输入旋转排序数组的元素:\n");
for(int i=0;i<size;i++){
scanf("%d",&arr[i]);
}
int min=findMin(arr,size);
printf("旋转排序数组中的最小值为:%d\n",min);
free(arr);
return 0;
}