算法:經典問題整理

題目描述1( A+B<=C問題)

  我們都喜歡 A+B=C 的問題,現在我們遇到了它的一個變形問題。給定 A+B<=C 的形式,並且規定A、B、C都是正整數。現在已知道了C的大小,請問有多少對不同的(A,B)滿足 A+B<=C (注:(1,2)與(2,1)認爲不同)。
輸入
有多組數據,輸入開始的第一行是一個整數 T (T<=100),代表數據組數。接下 T 行,每行一個正整數C(C<=10000)
輸出
對於每個C,輸出一行,包含一個正整數,代表符合條件的(A,B)的對數、
輸入樣例:
3
1
4
100
輸出樣例:
0
6
4950

分析說明: 如上的樣例表示輸入3組數據1、4、100 這三個數據(即C)滿足 A+B<=C的(A,B)對數分別爲0、6、4950。
如下,經分析可發現對於數據 k 即有 k*(k-1)/2 組(A,B)滿足 A+B<=C

		數據(值C)1		2		3		4		5 	...		k
滿足(A+B<=C)(A,B)對數: 0		1		3		6		10 	...		k*(k-1)/2

示例代碼

#include<stdio.h>

int main()
{
	int n,c;
	printf("輸入數據組數:"); 
	scanf("%d",&n);
	int i,a[n];
	for(i=0;i<n;i++)
	{
		scanf("%d",&c);
		a[i]=c;
	}
	printf("這%d組數據滿足A+B<=C的數據組數分別如下:\n",n);
	for(i=0;i<n;i++)
	{
		printf("%d\n",a[i]*(a[i]-1)/2);
	}
	return 0;
}

題目描述2(和爲目標值的兩個數的下標)

  給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那兩個整數,並返回他們的數組下標。你可以假設每種輸入只會對應一個答案。但是,你不能重複利用這個數組中同樣的元素。
分析示例:

給定 nums = [2, 7, 11, 15], target = 9

因爲 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

示例代碼

C語言:

#include<stdio.h>

void twoSum(int nums[],int target,int len)
{
	printf("這%d個數中相加的和爲9的兩個數在這數組中的下標爲:\n",len);
	for(int i=0;i<len;i++)
	{
		for(int j=i+1;j<len;j++)
		{
			if(nums[i]+nums[j]==target)
				printf("[%d,%d]\n",i,j);
		}
	}
	
}

int main()
{
	//int len = sizeof(arr) / sizeof(int);  //求數組長度
	int n,target=9;
	printf("請輸入你要輸入的數據長度(>=2):");
	scanf("%d",&n);
	int a[n];
	printf("請輸入這%d個數據:",n);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	} 
	twoSum(a,target,n);
	
	return 0;
} 

結構體數組哈希表:

#include<stdio.h>
struct sum
{
	int exi;//是否存在
	int local;//存在的位置
};
int a[8]={5,9,11,4,2,7,3,6};//隨意定義無序無重複
int flag=9;//兩數相加目標值
int len=8;//數組長度

int main()
{
	struct sum sum1[20];//長度爲最大數的值+1
	int i;
	for(i=0;i<20;i++)
	{//初始化
		sum1[i].exi=0;
		sum1[i].local=0;
	}
	int i1;
	for(i1=0;i1<len;i1++)
	{//給數組中存在的數賦值
		sum1[a[i1]].exi=1;
		sum1[a[i1]].local=i1;
	}
	int i2;
	for(i2=0;i2<len;i2++)
	{
		int num=flag-a[i2];
		if(sum1[num].exi==1)
		{//哈希表查找
			printf("%d,%d\n",i2,sum1[num].local);
			sum1[num].exi=0;//查找結束將這兩個加數刪除
			sum1[a[i2]].exi=0;
		}
	}
}

Java:

import java.util.Scanner;
/*
程序不足:當有多組數據的和等於目標值時,只返回第一組數據的下標
 */
public class Student {

    public static int[] twoSum(int[] nums,int target){
        for (int i=0;i<nums.length;i++)
        {
            for (int j=i+1;j<nums.length;j++)
            {
                if (nums[j]==target-nums[i])
                    //沒有數組名,但可以把數組作爲參數傳給方法;其餘方法這麼做會報錯
                    return new int[]{i,j};
            }
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println("輸入七個數:");
        Scanner sr=new Scanner(System.in);
        int arr[]=new int[7];
        for (int j=0;j<arr.length;j++)
        {
            arr[j]=sr.nextInt();
        }
        int[] test = twoSum(arr, 9);
        for (int i=0;i<test.length;i++)
        {
            System.out.print(test[i]+"\t");
        }
    }

}

Python:

def solution(nums,target):
	#如果列表長度小於2,則直接結束
	if len(nums) < 2:
            return
        #兩次循環列表,分別對列表中的所有可能的數字進行相加
        #循環兩次列表對應的時間複雜度爲O(n2)
        for i in range(0, len(nums) - 1):
            for j in range(i+1, len(nums)):
                if nums[i] + nums[j] == target:
                    return [i, j]

學習致謝:
http://c.biancheng.net/c/80/
https://blog.csdn.net/qq_37756688/article/details/89873902

題目描述3(水仙花數)

  求100-999之間所有的水仙花數(水仙花數:一個數的各個位數的立方和等於這個數本身,則這就是一個水仙花數)
例:407=444+000+777,則407是水仙花數

示例代碼

#include<stdio.h>
#include<math.h>

int main()
{
	printf("100-999之間的水仙花數爲:"); 
	for(int i=100;i<1000;i++)
	{
		//取得個位數
		int a=i%10;
		
		//取得十位數
		int b=i/10%10;
		
		//取得百位數
		int c=i/100;
		//pow(a,3)等價於a*a*a,需引用math.h頭文件 
		if(pow(a,3)+pow(b,3)+c*c*c==i)
		{
			printf("%d\n",i);
		}
	}
	
	return 0;
}

題目描述4(冒泡排序的應用)

  爲增進大家友情週末要進行男子拔河比賽。爲了比賽的可看性,現要選出體重較重的男同學,所以按照從輕到重的體重順序佔成一排進行篩選。求出這些男同學的體重從輕到重的排序。
輸入
  輸入數據有多組,第一行輸入男同學的人數n(1<=n<=10),第二行分別輸入他們的體重m(150>m>0),以回車作爲結束標誌.
輸出
輸出他們的體重由低到高的序列。結果保留2位小數。
輸入樣例:
5
68.00 59.00 66.67 55.55 45.00

輸出樣例:
45.00 55.55 59.00 66.67 68.00

示例代碼

#include<stdio.h>

//冒泡排序 
void BubbleSort(float arr[],int len)
{
	for (int i = 0; i < len-1; i++)
	{
		for (int j = 0; j < len-1-i; j++)
		{
			if (arr[j]>arr[j+1])
			{
				float temp=arr[j];
				arr[j]=arr[j+1];
				arr[j+1]=temp;
			}
		}
	}
}

int main()
{
	int n;
	printf("輸入男同學的人數n(1<=n<=10):"); 
	scanf("%d",&n);
	float arr[n];
	printf("輸入這%d人的體重:\n",n); 
	for(int i=0;i<n;i++)
	{
		scanf("%f",&arr[i]);
	}
	
	BubbleSort(arr,n);		//調用BubbleSort方法 
	printf("排序後(低到高):\n"); 
	for (int j = 0; j < n; j++)
	{
		/**
		* C++此處可用該語句實現:
		* cout.precision(2);
		* cout<<fixed<<arr[j]<<"\t";
		*/
		printf("%.2f\t",arr[j]);
	}
	
	return 0;
}

題目描述5(湊夠所需最少張數)

  會長想給一直頑強拼搏的的參賽隊員發一筆獎金。但是會長就在考慮一個問題:如果每個同學的獎金額都知道,最少需要準備多少張人民幣,才能在給每位同學發獎金的時候都不用會長找零呢?這裏假設同學的獎金都是正整數,單位元,人民幣一共有100元、50元、20元、10元、5元和1元六種。
輸入
第一行爲正整數整數n(n<100),表示同學的人數。第二行是n個同學的獎金。
輸出
對於每個測試實例輸出一個整數x,表示至少需要準備的人民幣張數。
輸入樣例:
3
1 2 3
輸出樣例:
6

示例代碼

#include <stdio.h>

int main()
{
	int m100,m50,m20,m10,m5,m1;
	
	int n;
	printf("輸入同學的人數n(n<100):"); 
	scanf("%d",&n);
	
	int arr[n];
	printf("輸入這%d個同學的獎金:\n",n); 
	for(int i=0;i<n;i++)
	{
		scanf("%d",&arr[i]);
	}
	
	int b[n];	//保存每個學生分別需要幾張人民幣 
	for(int j=0;j<n;j++)
	{
		m100 = arr[j] / 100;	//m100:得到100元需要幾張 
		arr[j] = arr[j] % 100;	//求餘:得到減去幾張100元后剩餘的數據

		m50 = arr[j] / 50;
		arr[j] = arr[j] % 50;

		m20 = arr[j] / 20;
		arr[j] = arr[j] % 20;

		m10 = arr[j] / 10;
		arr[j] = arr[j] % 10;

		m5 = arr[j] / 5;
		arr[j] = arr[j] % 5;
		
		m1= arr[j];		//m1:得到1元需要幾張 
		
		b[j]=m100+m50+m20+m10+m5+m1;
	}
	
	int sum=0;
	for(int y=0;y<n;y++)//將每個同學的人民幣數量加起來得到總的數量 
	{
		sum=sum+b[y];
	}
	printf("最少需要準備的人民幣張數爲:%d\n",sum);
	
	return 0;
}

題目描述6(結構體應用一)

  有N(N<=1000)名同學參加了期末考試,並且獲得了每名同學的姓名(不超過8個字符的字符串,沒有空格)、語文、數學、英語成績(均爲不超過150的自然數)。總分最高的學生就是最厲害的,請輸出最厲害學生各項信息(姓名、各科成績)。如果有多個總分相同的學生,輸出第一位的學生信息即可。
輸入格式

  • 第一行 學生人數N
  • 接下來N行,每一行是一個學生的信息

輸出格式

  • 總分最高的學生信息

輸入樣例:
3
senpai 114 51 4
ax 114 10 23
fafa 51 42 60
輸出樣例:
senpai 114 51 4

示例代碼

#include<stdio.h>
#define N 1000
//自然數:指零和一切正整數
struct{
	char   name[8];  //姓名
	int    chinese;
	int    math;
	int    english;
}s[N];

void input(int n)
{
	for(int i=0;i<n;i++)
	{
		printf("輸入姓名:");
		scanf("%s",s[i].name);
		
		printf("輸入語文成績:");
		scanf("%d",&s[i].chinese);
		
		printf("輸入數學成績:");
		scanf("%d",&s[i].math);
		
		printf("輸入英語成績:");
		scanf("%d",&s[i].english);
				
		printf("\n");

	}

}

int sortl(int n)
{
	int max=s[0].chinese+s[0].math+s[0].english;
	int max_inx = 0;
	for(int i=1;i<n;i++)
	{
		if(s[i].chinese+s[i].math+s[i].english>max)
		{
			max=s[i].chinese+s[i].math+s[i].english;
			max_inx=i;
		}
	}
	
	
	return max_inx;
}

int main()
{
	int n;
	printf("輸入學生人數:");
	scanf("%d",&n);
	input(n);
	
	int max_inx=sortl(n);
	printf("%s\t%d\t%d\t%d\n",s[max_inx].name,s[max_inx].chinese,s[max_inx].math,s[max_inx].english); 
	
	return 0;
}

題目描述7(結構體應用二)

  有N(N<=1000)名同學,每名同學需要設計一個結構體記錄以下信息:學號(不超過100000的正整數)、學業成績和素質拓展成績(都是0到100的正整數)、綜合分數(實數)。每行讀入學生的姓名、學業成績和素質拓展成績,並且計算綜合分數(分別按70%和30%的權重累加),存入結構體中。分析每名學生是否“優秀”。優秀的定義是:學業成績和素質拓展總分大於140分,且綜合分數不小於80分。
輸入格式

  • 第一行,一個整數N代表學生人數
  • 接下來N行,每一行3個整數,依次代表學號、學業成績和素質拓展成績

輸出格式
如果第i名學生是優秀的,輸出Excellent,否則輸出Not excellent

示例代碼

#include<stdio.h>
#define N 1000
//double數據輸入格式爲%lf,輸出格式爲%f 
struct{
	int    xh;
	int    xy;
	int    sz;
	double zh;
}s[N];

void input(int n)
{
	for(int i=0;i<n;i++)
	{
		printf("\n輸入第%d名學生學號:",i+1);
		scanf("%d",&s[i].xh);
		
		printf("輸入學業成績:");
		scanf("%d",&s[i].xy);
		
		printf("輸入素質拓展成績:");
		scanf("%d",&s[i].sz);
		
		s[i].zh= (s[i].xy*0.7)+(s[i].sz*0.3);
				
		printf("\n");

	}

}

void printf1(int n)
{
	for(int i=0;i<n;i++)
	{
		if((s[i].xy+s[i].sz)>140 && s[i].zh>=80)
		{
			printf("Excellent\n");
		} else{
			printf("Not Excellent\n");
		}
	} 
}  

int main()
{
	int n;
	printf("輸入學生人數:");
	scanf("%d",&n);
	input(n);
	
	printf1(n);
	
	return 0;
}

題目描述8(“數字黑洞”)

  給定任一個各位數字不完全相同的正整數,如果先把四個數字按非遞增排序,再按非遞減排序,然後用第一個數減去第二個數,將得到一個新的數字,一直重複此過程,很快會停在有“數字黑洞”之稱的6174,這個神奇的數字也叫Kaprekar。輸入一個四位數,求過幾次變換能得到6174
輸入樣例1: 6767
輸出樣例1:
7766-6677=1089
9810-0189=9621
9621-1269=8352
8532-2358=6174
4次


輸入樣例2: 2222
輸出樣例2: 2222-2222=0


分析: 假設輸入的數字經過num次變換後能得到6174,先將輸入的那個四位整數拆成4個數字放入一個數組中,然後用這4個數字升序排列、降序排列分別組成最小的數字和最大的數字,用大數減去小數可以得到一個新的數字,如果新的數字是6174就輸出num即可。

示例代碼

#include <bits/stdc++.h>
using namespace std;

//把數組中的數按照下標順序組成一個新的數字
int arr2num(int a[])   
{
    int n = 0;
    for(int i = 0; i < 4; i++)
    {
        n = n*10 + a[i];
    }
    return n;
}
 
int main()
{
    int n;
    cin >> n;
    int a[4];
    int num = 0;   //統計次數 
    do{
        for(int i = 0; i < 4; i++)   //把各位數存入數組裏面
        {
            a[i] = n%10;
            n /= 10;
        }
        sort(a,a+4);   //升序排列
        int x = arr2num(a);   //得到由數組a中元素組成的最小數字
        sort(a,a+4,greater<int>());  //降序排列
        int y = arr2num(a);  //得到由數組a中元素組成的最大數字
        n = y-x;   //作差得到一個新的四位數
        printf("%d-%d=%d\n",y,x,n); 
        if(n==0) break; 
        num++;
    }while(n != 6174);
    cout << num<<"次" << endl;
    
    return 0;
}

題目描述9

未完待續…

編程之外

  積累積累,每天進步一點點就好,這篇博客將持續不定期更新下去!
歡迎關注我的個人公衆號,一起成長😁😁😁
在這裏插入圖片描述
在這裏插入圖片描述

編程之外
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章