在路上遇见的一些算法问题
在每天码代码的过程中,有时候会遇见一些比较经典的算法问题。我想总结一下最近遇见的一下算法。
问题:
有一个桶,里面有白球和黑球各100个,规则如下:
1.每次随机从桶中取出两个球
2.如果是两个同色的球,就再放入一个黑球
3.如果是两个异色的球,就再放入一个白球
问:最后桶中只剩下一个黑球的概率是多少?(白球数不管)
答:
我们可一个用一个set(黑球数量,白球数量)来表示桶中的黑球和白球的个数。从桶中取出球后,只可能是下列三种操作:
1.取出的是两个黑球,则放回一个黑球:(-2, 0) + (1, 0) = (-1, 0)
2.取出的是两个白球,则放回一个黑球:(0, -2) + (1, 0) = (1, -2)
3.取出的是一黑一白,则放回一个白球:(-1, -1) + (0, 1) = (-1, 0)
根据上面的规则,我们可以发现:白球的数量变化情况只能是不变或者-2,也就是说,如果是100个白球,白球永远不可能是1个的情况,那么问题的解法就很简单了,就是只剩下黑球的概率为100%。
问:给你一个自然数N,求【6,N】之内所有素数中两两之和为偶数的那些偶数。
用哥德巴赫猜想(欧拉版):任一大于2的偶数都可写成两个质数之和
答:故只需列出所有偶数即可。[6,N]的素数之和最小偶数为14(允许相同素数的情况下),最大偶数为最大素数的2倍。
问:有一种毒药,猪喝了15分钟内会死亡(假设猪喝水不花费时间,而且不是定时死亡)。现在我们有1000桶水,需要用猪去测出哪桶水有毒,需要几头猪?
答:使用数列(五维空间)方法,5头。
问:排序方法有哪些?
答:
1.冒泡
void BubbleSort(int arr[],int count)
{
int temp=0;
bool swapped=false;
for(int i=1;i<count;i++)
{
swapped=false;
for(int j=count-1;j>=i;j--)
{
if(arr[j-1]>arr[j])
{
temp=arr[j-1];
arr[j-1]=arr[j];
arr[j]=temp;
}
swapped=true;
}
if(!swapped)//本趟排序未发生交换,提前终止算法
return;
}
}
2.二分查找
int BinSearch(int *arr, int n , int key)
{
int low = 0;
int high = n-1;
int mid;
if(arr[low] == key)
{
return 0;
}
while(low <= high)
{
mid = low + ((high - low)/2);
if(arr[mid] == key)
{
return mid;
}
if(arr[mid] > key)
high = mid - 1;
else
low = mid + 1;
}
return -1;
}
3.快排
#include <stdio.h>
int a[100] = { 1, 2, 8, 7, 9, 5, 6, 4, 3, 66, 77, 33, 22, 11 };
/* 输出数组前n各元素*/
void prt(int n) {
int i;
for (i = 0; i < n; i++) {
printf("%d\t", a[i]);
}
printf("\n");
}
/* 数据交换*/
void swap(int *a, int *b)
{
int tmp;
tmp = *a; *a = *b; *b = tmp;
}
void quick_sort(int a[], int left, int right)
{
int i = left + 1, j = right;
int key = a[left];
if (left >= right) return;
/* 从i++和j--两个方向搜索不满足条件的值并交换 *
* 条件为:i++方向小于key,j--方向大于key */
while (1) {
while (a[j] > key) j--;
while (a[i] < key&&i<j) i++;
if(i >= j) break;
swap(&a[i],&a[j]);
if(a[i]==key)j--;
else i++;
}
/* 关键数据放到‘中间’*/
swap(&a[left],&a[j]);
if(left < i - 1) quick_sort(a, left, i - 1);
if(j + 1 < right) quick_sort(a, j + 1 , right);
}
int main(void) {
/* 排序与输出*/
quick_sort(a, 0, 13);
prt(14);
return 0;
}
问:101个硬币中有一个假币,有一个无砝码的天平,称两次,判断假币比真币重还是轻。
答:
方案1:把101个硬币平均分成三份,分别是:33,33,35,把两 堆33个放在天平上称。
1、如果平衡,说明这66个都是真的。然后从这两堆共66个中取出35个,与第三堆的35个分别放在天平的左右盘中称,这样,第三堆所在的天平的那一端的轻重就是假币的轻重情况。
2、如果两 个33放在天平上不平衡,说明第三堆的35个是真的。取下轻的一端的33个,从第三堆中取33个放在上面,如果平衡,说明取下的一堆中有假币,假币比真的轻。如果不平衡,只有一种结果,第三堆与取下的一堆一样,都比那一堆轻,说明假的比真的重。
方案2:将硬币按A组(50)、B组(50)、C组(1)分组,先比较A、B两组:
1>.若A=B,则C为假币,再用A或B中任一个与C比,C重则假币重,C轻则真币重
2>.若A!=B,则A或B中含假币,将A组一分为二:A1(25)、A2(25),比较A1、A2:
<1>.若A1=A2,则A为真币,故:A>B => 真币重;A<B => 假币重
<2>.若A1!=A2,则A含假币,故:A<B => 真币重;A>B => 假币重
问:有一把手枪(无线子弹),当第一个人拿到手枪会打死旁边的人,然后将手枪传下去。1000个人拿着手枪围着圈坐在一起,请问最后存活的是第几个人?
答:第977个 【n-2^j】* 2+1;
java实现
public class NewtonMethod {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入参与人数");
String scan=scanner.next();
int a=Integer.parseInt(scan);
NewtonMethod newtonMethod = new NewtonMethod();
//int x = newtonMethod.sqrt(2);
int o = newtonMethod.HA(a);
System.out.println("幸运人数是第"+o+"位");
//System.out.print(x);
}
public int HA(int n)
{
int k=0;
for( double i=0;Math.pow(2,i)<n;i++)
{
double sum=(n-Math.pow(2,i))*2+1;
k = (int)sum;
}
return k;
}}
问:从最多10个整数的集合中,分成两组(不需平均分组,可以一组1个、另一组9个),要求只要两组的总和差值最小,还有就是集合里的数量可奇可偶。
答:
public class RandomlyAssigned {
public static void main(String[] args) {
// 从大到小排好序的数组
int arr[]={100,91,81,77};
List<Integer> sum1=new ArrayList<Integer>();
List<Integer> sum2=new ArrayList<Integer>();
int a=0;
int b=0;
for(int i=0;i<arr.length;i++){
if(a<=b){
sum1.add(arr[i]);
a+=arr[i];
}else{
sum2.add(arr[i]);
b+=arr[i];
}
}
System.out.println("A:" + sum1 + ", B: " + sum2 + ", 差值:" + Math.abs(a - b));
}
}
升级版
package com.Test.method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
/**
* @author Sakura
* @function 分组选出差值最小的两组
* @date 2018-12-7
* @modify date ,modify author,modify cause
*
*/
public class RandomlyAssigned {
public static void main(String[] args) {
System.out.print("请输入您要分配的数组长度和数组 如:3组 分别是 1 2 3\n");
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int m = scanner.nextInt();
int[] arr = new int[m];
for (int i = 0; i < m; i++) {
arr[i] = scanner.nextInt();
}
System.out.print("您输入的数组是:\n" + Arrays.toString(arr) + "\n");
RandomlyAssigned RanASS = new RandomlyAssigned();
RanASS.BubbleSort(arr, m);
RanASS.Random(arr);
}
}
public void BubbleSort(int arr[], int count) {
int temp = 0;
boolean swapped = false;
for (int i = 1; i < count; i++) {
swapped = false;
for (int j = count - 1; j >= i; j--) {
if (arr[j - 1] < arr[j]) {
temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
swapped = true;
}
}
System.out.print("由大到小排列后:\n" + Arrays.toString(arr) + "\n");
}
public void Random(int arr[]) {
int sum1 = 0;
int sum2 = 0;
List<Integer> group1 = new ArrayList<Integer>();
List<Integer> group2 = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++) {
if (sum1 <= sum2) {
group1.add(arr[i]);
sum1 += arr[i];
} else {
group2.add(arr[i]);
sum2 += arr[i];
}
}
System.out.println("分组后为:\n" + "A:" + group1 + ", B: " + group2
+ "\n 差值:" + Math.abs(sum1 - sum2));
}
}
上一篇: 多线程安全的单例模式
下一篇: HomeBrew安装软件报错的一些遇见
推荐阅读
-
windows 2008 r2 下面搭建 iis+sql server +php5.6 环境遇见的一些问题记录一下,r2php5.6
-
关于在 win2000 下安装 mysql 的一些问题!_PHP教程
-
vue在苹果手机上的一些问题(这次写的h5公众号)
-
Tensorflow 在c++上的编译和遇到的一些问题
-
关于在 win2000 下安装 mysql 的一些问题!_PHP教程
-
亚马逊站外推广过程中常遇见的一些问题
-
jquery在项目中做复选框时遇到的一些问题笔记
-
DEV C++在win7系统中安装以及遇到的一些问题解决
-
在SAE上部署Python的Django框架的一些问题汇总
-
在WinForms里嵌入MediaPlayer的一些版本问题, tlbimp导入, 以及不导入而纯用C#+字符串来动态调用.