几个面试题
求一算法:在m个整数中,求n个数的组合,若这n个数的和等于sum,则将这n个数打印出来。(m,n均不定,1<=n<=m,m个数的值,sum的值由界面输入.)
看起来好像很简单,实际写起来好像还有点复杂,希望各位提供算法和代码,(兼顾一下算法的效率,若m的值比较大,怎么办?总不至于在机器面前等上几十分钟吧?m的值小于100,平常一般在20左右.)不胜感激!!!!!
a:我记得以前有写过的
具体方法如下
1,进行排序,从小到大
2,先拿一位数进行判断,如果后面的数大了,退出
3,拿二位数进行判断,从第一个开始,然后配对的是后面的数,如果大,退出,然后拿第2个数,
递归实现以后的吧,
反正是找到退出条件,
b:所有可能的组合
还是只要一组
下面可得到一个组合
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure Sum(a: array of Integer; x: Integer);
procedure Button1Click(Sender: TObject);
function knap(S, n: Integer): Integer;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
a: array [0..25] of Integer;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
for i := 0 to 25 do
begin
Randomize();
a[i] := Abs(Random(50));
end;
end;
procedure TForm1.Sum(a: array of Integer; x: Integer);
var
i,j,temp: Integer;
begin
if ( knap(50,i) > 0 )then Memo1.Lines.Add( 'OK')
else continue;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i,j,temp: Integer;
begin
for i := Low(a) to High(a) -1 do
for j:= i+1 to High(a) do
begin
if a[i] > a[j] then
begin
temp := a[i];
a[i] := a[j];
a[j] := temp;
end;
end;
Sum(a, 50);
end;
function TForm1.knap(S, n: Integer): Integer;
begin
if(S = 0) then
begin
result := 1;
exit;
end;
if ( (s< 0)or ( (s>0) and (n < 1) )) then
begin
result := 0;
exit;
end;
if (knap(s-a[n], n-1) > 0) then
begin
Memo1.Lines.Add(IntToStr(a[n]));
result := 1;
exit;
end;
Result := knap(s,n-1);
end;
end.
2.
[一个算法问题]从m个数中任取n个数的组合
输入为“1,3,5,7,9”这5个
输出为
1,3,5
1,3,7
1,3,9
1,5,7
1,5,9
1,7,9
3,5,7
3,5,9
3,7,9
5,7,9
该怎么实现这个算法?
//C++ Code;
//you can change
int index[4]; //used to record the indexes of the selected
int cur; //record the number with the lowest index to be selected
cur = 0;
void fun(int *index,int step)
{
step++;
if(step>3)
{
cout<<array[index[1]]<<" "<<array[index[2]]<<........... //print the result
return;
}
else if(step<=3)
{
for(i=cur;i<5;i++)
{
int tmp = cur;
index[step] = cur;
cur++;
fun(index,step);
cur = tmp;
}
}
}
void main()
{
fun(index,0);
}
3.
编程实现1到N个数的所有排列组合
如:
n = 3
则得到的序列如下:123, 132, 213, 231, 312, 321
我的实现如下,大家看看如何:
using System;2
using System.Collections.Generic;3
using System.Text;4

5
namespace ConsoleApplication426
{7
class Program8
{9
static void Main(string[] args)10
{11
int n = 4;12

13
CreateList creator = new CreateList(n);14

15
creator.Creat();16
}17
}18

19
public class CreateList20
{21
private struct Num22
{23
public int num;24
public State state;25
}26

27
private enum State { LEFT = -1, RIGHT = 1, STAY = 0 };28

29
private int _n;30

31
private int _totle;32

33
private Num[] _nums;34

35
public CreateList(int n)36
{37
if (n < 1)38
{39
throw new Exception("N should large than zero.");40
}41

42
_n = n;43

44
_nums = new Num[_n];45

46
for (int i = 0; i < _n; i++)47
{48
_nums[i].num = i + 1;49
_nums[i].state = State.LEFT;50
}51

52
_totle = getTotole(_n);53
}54

55
private int getTotole(int n)56
{57
if (n == 1)58
{59
return n;60
}61
else62
{63
return n * getTotole(n - 1);64
}65
}66

67
/// <summary>68
/// Find the lagest num index which need move.69
/// </summary>70
/// <returns> the index of the lagest num which need move.</returns>71
private int getLargestMoveNumIndex()72
{73
int maxNum = 0;74
int index = -1;75

76
for (int i = 0; i < _n; i++)77
{78
if (_nums[i].state == State.LEFT && i == 0)79
{80
continue;81
}82

83
if (_nums[i].state == State.RIGHT && i == _n - 1)84
{85
continue;86
}87

88
if (_nums[i].state != State.STAY)89
{90
if (maxNum < _nums[i].num)91
{92
maxNum = _nums[i].num;93
index = i;94
}95
}96
}97

98
return index;99
}100

101
/// <summary>102
/// Swap two nums.103
/// </summary>104
/// <param name="index1"> the 1st num's index.</param>105
/// <param name="index2"> the 2nd num's index.</param>106
private void swap(int index1, int index2)107
{108
Num tempNum = _nums[index1];109

110
_nums[index1] = _nums[index2];111
_nums[index2] = tempNum;112
}113

114
/// <summary>115
/// Calculate nums state which are large than last move num.116
/// </summary>117
/// <param name="largestMoveNumIndex"></param>118
private void caluState(int lastNum)119
{120
for (int i = 0; i < _n; i++)121
{122
if (_nums[i].num > lastNum)123
{124
if (_nums[i].state == State.LEFT)125
{126
_nums[i].state = State.RIGHT;127
}128
else if (_nums[i].state == State.RIGHT)129
{130
_nums[i].state = State.LEFT;131
}132
}133
}134
}135

136
/// <summary>137
/// Get the nums vaule.138
/// </summary>139
/// <returns>The nums vaule.</returns>140
private System.Int64 getNumVaule()141
{142
System.Int64 numVaule = 0;143

144
for (int i = 0; i < _n; i++)145
{146
numVaule += (System.Int64)(_nums[i].num * Math.Pow(10, _n - i - 1));147
}148

149
return numVaule;150
}151

152
public System.Int64 CreatOneNum()153
{154
int largestMoveNumIndex = getLargestMoveNumIndex();155

156
if (largestMoveNumIndex != -1)157
{158
int lastNum = _nums[largestMoveNumIndex].num;159

160
int index = largestMoveNumIndex + (int)_nums[largestMoveNumIndex].state;161

162
swap(index, largestMoveNumIndex);163

164
caluState(lastNum);165
}166

167
return getNumVaule();168
}169

170
public void Creat()171
{172
for (int i = 0; i < _totle; i++)173
{174
System.Int64 num = CreatOneNum();175

176
System.Console.WriteLine(num);177
}178

179
System.Console.WriteLine("Totle:" + _totle);180
}181
}182
}183

4.
题目描述:
有3种面额的硬币:1分,2分和5分的。现在有100枚这样的硬币,面额总和是2.47元,求共有多少种可能,且1分,2分和5分的硬币各有多少。
解题思路:
假设1分,2分和5分的硬币个数分别是x,y,z个。
则有:
x + y + z =100
x+2y+5z=247
可得:
X = 3z – 47
Y = 147-4z
又知道
x >= 0
y>=0
z>=0
5z<=247
可得:
16<=z<=36
问题得解。
问题的证明:
用c#代码实现,并输出每种解的值。
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int num = CaluSovNum();
}
private static int CaluSovNum()
{
int x, y, z;
int num = 0;
for (z = 16; z <= 36; z++)
{
x = 3 * z - 47;
y = 147 - 4 * z;
if (x <0 || y <0 || x + y + z != 100 || x + 2 * y + 5 * z != 247)
{
throw new Exception("Error");
}
num++;
Console.WriteLine("1分钱的硬币个数是{0}, 2分钱的硬币个数是{1}, 5分钱的硬币个数是{2}",
x, y, z);
}
return num;
}
}
}
http://www.cnblogs.com/gpcuster/archive/2007/12/19/1005666.html


浙公网安备 33010602011771号