L
lijun4183
Unregistered / Unconfirmed
GUEST, unregistred user!
同志们真爱钻牛角尖哦
今天为了这个问题烦恼了很久,终于搞定了
哎,用这种题会考死人的。
虽然我的算法没有采用额外数组,但是使用了递归,所以开销在堆栈中,我个人觉得
这个问题仅仅存在学术上的意义,没有什么实用价值
不想写思想了,同志们自己研究吧,算法代码如下
function GetOddCount(piInteger;ACount:Integer): integer;//计算奇数个数
var i:integer;
begin
Result:=0;
for i:=0 to ACount-1do
begin
if (pi^ mod 2)=1 then
Inc(Result);
Inc(pi);
end;
end;
procedure Swap(psi, pdi: pInteger);//交换两个整数
var tmp:Integer;
begin
tmp := psi^;
psi^ := pdi^;
pdi^ := tmp;
end;
procedure OddEvenDealV2(piInteger;ACount,OddCount:integer;
CurValue:integer;var CurpiInteger;var PreEvenCount:integer);
var pdiInteger;
ReplaceValue:Integer;
begin
if (Integer(CurPi)-Integer(pi))>=sizeof(Integer)*ACount then
exit;
if (CurValue mod 2)=1 then
//奇数
begin
//奇数只可能往前移动
pdi:=PInteger(Integer(Curpi)-sizeof(Integer)*PreEvenCount);
if pdi<>Curpi then
pdi^:=CurValue;
Inc(Curpi);
end
else
//偶数
begin
pdi:=PInteger(Integer(pi)+sizeof(Integer)*(ACount-1-PreEvenCount));
if pdi=Curpi then
begin
Inc(PreEvenCount);
Inc(Curpi);
end
else
begin
ReplaceValue:=pdi^;
pdi^:=CurValue;
Inc(PreEvenCount);
Inc(Curpi);
while Integer(pdi)-Integer(Curpi)>=0do
begin
if Integer(pdi)-Integer(Curpi)=0 then
OddEvenDealV2(pi,ACount,OddCount,ReplaceValue,Curpi,PreEvenCount)
else
OddEvenDealV2(pi,ACount,OddCount,Curpi^,Curpi,PreEvenCount);
end;
end;
end;
end;
procedure OddEvenDeal(piInteger;ACount:integer);
var TempPi,TempDPiinteger;
TempOddCount,TempPreEvenCount,i:integer;
begin
TempPi:=pi;
TempOddCount:=GetOddCount(pi,ACount);//O
TempPreEvenCount:=0;
//下面调用使:奇数按原来顺序排在前面,偶数按照原来的逆顺序排列在后面
//以下算法虽然采用了递归,但是时间效率为O
//因为每个入口都调用了Inc(TempPi),最多处理n次
while Integer(TempPi)-Integer(pi)<sizeof(Integer)*ACountdo
OddEvenDealV2(pi,ACount,TempOddCount,TempPi^,TempPi,TempPreEvenCount);
//最后调转偶数的顺序 O(n/2)
for i:=0 to (TempPreEvenCount div 2)-1do
begin
TempPi:=PInteger(Integer(pi)+sizeof(Integer)*(TempOddCount+i));
TempDPi:=PInteger(Integer(pi)+sizeof(Integer)*(ACount-1-i));
Swap(TempPi,TempDPi);
end;
end;
测试代码
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
A:array[0..19] of Integer=(2,4,3,5,8,19,20,22,33,35,10,11,99,98,96,94,92,90,71,73);
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
OddEvenDeal(@a[0],20);
for i:=0 to 19do
begin
Memo1.Lines.Add(IntToStr(a));
end;
end;
今天为了这个问题烦恼了很久,终于搞定了
哎,用这种题会考死人的。
虽然我的算法没有采用额外数组,但是使用了递归,所以开销在堆栈中,我个人觉得
这个问题仅仅存在学术上的意义,没有什么实用价值
不想写思想了,同志们自己研究吧,算法代码如下
function GetOddCount(piInteger;ACount:Integer): integer;//计算奇数个数
var i:integer;
begin
Result:=0;
for i:=0 to ACount-1do
begin
if (pi^ mod 2)=1 then
Inc(Result);
Inc(pi);
end;
end;
procedure Swap(psi, pdi: pInteger);//交换两个整数
var tmp:Integer;
begin
tmp := psi^;
psi^ := pdi^;
pdi^ := tmp;
end;
procedure OddEvenDealV2(piInteger;ACount,OddCount:integer;
CurValue:integer;var CurpiInteger;var PreEvenCount:integer);
var pdiInteger;
ReplaceValue:Integer;
begin
if (Integer(CurPi)-Integer(pi))>=sizeof(Integer)*ACount then
exit;
if (CurValue mod 2)=1 then
//奇数
begin
//奇数只可能往前移动
pdi:=PInteger(Integer(Curpi)-sizeof(Integer)*PreEvenCount);
if pdi<>Curpi then
pdi^:=CurValue;
Inc(Curpi);
end
else
//偶数
begin
pdi:=PInteger(Integer(pi)+sizeof(Integer)*(ACount-1-PreEvenCount));
if pdi=Curpi then
begin
Inc(PreEvenCount);
Inc(Curpi);
end
else
begin
ReplaceValue:=pdi^;
pdi^:=CurValue;
Inc(PreEvenCount);
Inc(Curpi);
while Integer(pdi)-Integer(Curpi)>=0do
begin
if Integer(pdi)-Integer(Curpi)=0 then
OddEvenDealV2(pi,ACount,OddCount,ReplaceValue,Curpi,PreEvenCount)
else
OddEvenDealV2(pi,ACount,OddCount,Curpi^,Curpi,PreEvenCount);
end;
end;
end;
end;
procedure OddEvenDeal(piInteger;ACount:integer);
var TempPi,TempDPiinteger;
TempOddCount,TempPreEvenCount,i:integer;
begin
TempPi:=pi;
TempOddCount:=GetOddCount(pi,ACount);//O
TempPreEvenCount:=0;
//下面调用使:奇数按原来顺序排在前面,偶数按照原来的逆顺序排列在后面
//以下算法虽然采用了递归,但是时间效率为O
//因为每个入口都调用了Inc(TempPi),最多处理n次
while Integer(TempPi)-Integer(pi)<sizeof(Integer)*ACountdo
OddEvenDealV2(pi,ACount,TempOddCount,TempPi^,TempPi,TempPreEvenCount);
//最后调转偶数的顺序 O(n/2)
for i:=0 to (TempPreEvenCount div 2)-1do
begin
TempPi:=PInteger(Integer(pi)+sizeof(Integer)*(TempOddCount+i));
TempDPi:=PInteger(Integer(pi)+sizeof(Integer)*(ACount-1-i));
Swap(TempPi,TempDPi);
end;
end;
测试代码
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
A:array[0..19] of Integer=(2,4,3,5,8,19,20,22,33,35,10,11,99,98,96,94,92,90,71,73);
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
OddEvenDeal(@a[0],20);
for i:=0 to 19do
begin
Memo1.Lines.Add(IntToStr(a));
end;
end;