您的位置:首页 > 职场人生

编程面试题

2017-03-06 13:48 211 查看
1、char转换成int

int i_offset = 0;
int i_count = GetValue(pBuffer+i_offset,4);
i_offset += 4;

DWORD GetValue(const BYTE *pBuffer , int i_length)
{
DWORD i_value=0;
if (NULL==pBuffer || i_length<=0) return i_value;

switch(i_length)
{
case 0:
i_value=0;
break;
case 1:
i_value=*pBuffer ;
break;
case 2:
i_value=GetWORD( pBuffer );
break;
case 3://可能涉及到大头 小头; 暂时以Intel为
i_value=GetWORD(pBuffer +1) + ( *pBuffer <<16);
break;
case 4:
i_value=GetDWORD(pBuffer );
break;

default:
break;
}

return i_value;
}

int GetWORD( const unsigned char *buffer)
{
unsigned int value=buffer[0] ;
value<<=8 ;
value+=buffer[1] ;
return (int)value ;
}


2、有个二级单链表,其中每个元素都含有一个指向一个单链表的指针。写程序把这个二级链表展开成一级单链表。

这个二级单链表只包括一些head:
public class Link
{
public Link Next;
public int Data;
public Link(Link next, int data)
{
this.Next = next;
this.Data = data;
}
}
public class CascadeLink
{
public Link Next;
public CascadeLink NextHead;
public CascadeLink(CascadeLink nextHead, Link next)
{
this.Next = next;
this.NextHead = nextHead;
}
}

下面做一个二级单链表,GenerateLink1和GenerateLink2方法在前面都已经介绍过了:
public static CascadeLink GenerateCascadeLink()
{
Link head1 = GenerateLink1();
Link head2 = GenerateLink2();
Link head3 = GenerateLink1();
CascadeLink element3 = new CascadeLink(null, head3);
CascadeLink element2 = new CascadeLink(element3, head2);
CascadeLink element1 = new CascadeLink(element2, head1);
CascadeLink head = new CascadeLink(element1, null);
return head;
}
就是说,这些单链表的表头head1、head2、head3、head4……,它们组成了一个二级单链表head:null –> head1 –> head2 –> head3 –> head4
–>

我们的算法思想是: 进行两次遍历,在外层用curr1遍历二级单链表head,在内层用curr2遍历每个单链表:
public static Link GenerateNewLink(CascadeLink head)
{
CascadeLink curr1 = head.NextHead;
Link newHead = curr1.Next;
Link curr2 = newHead;
while (curr1 != null)
{
curr2.Next = curr1.Next.Next;
while (curr2.Next != null)
{
curr2 = curr2.Next;
}
curr1 = curr1.NextHead;
}
return newHead;
}

其中,curr2.Next = curr1.Next.Next; 这句话是关键,它负责把上一个单链表的表尾和下一个单链表的非空表头连接起来。


3、已知一个单向链表的头,请写出删除其某一个结点的算法,要求,先找到此结点,然后删除。

slnodetype *Delete(slnodetype *Head,int key){}中if(Head->number==key)
{
Head=Pointer->next;
free(Pointer);
break;
}
Back = Pointer;
Pointer=Pointer->next;
if(Pointer->number==key)
{
Back->next=Pointer->next;
free(Pointer);
break;
}
void delete(Node* p)
{
if(Head = Node)
while(p)
}


4、用链表模拟大整数加法运算

例如:9>9>9>NULL + 1>NULL =>
1>0>0>0>NULL
肯定是使用递归啦,不然没办法解决进位+1问题,因为这时候要让前面的节点加1,而我们的单链表是永远指向前的。
此外对于999+1=1000,新得到的值的位数(4位)比原来的两个值(1个1位,1个3位)都多,所以我们将表头的值设置为0,如果多出一位来,就暂时存放到表头。递归结束后,如果表头为1,就在新的链表外再加一个新的表头。
//head1 length > head2, so M > N
public static int Add(Link head1, Link head2, ref Link newHead, int M, int N)
{
// goto the end
if (head1 == null)
return 0;
int temp = 0;
int result = 0;
newHead = new Link(null, 0);
if (M > N)
{
result = Add(head1.Next, head2, ref newHead.Next, M – 1, N);
temp = head1.Data + result;
newHead.Data = temp % 10;
return temp >= 10
1 : 0;
}
else // M == N
{
result = Add(head1.Next, head2.Next, ref newHead.Next, M – 1, N – 1);
temp = head1.Data + head2.Data + +result;
newHead.Data = temp % 10;
return temp >= 10
1 : 0;
}
}
这里假设head1比head2长,而且M、N分别是head1和head2的长度。


5、单链表交换任意两个元素(不包括表头)

先一次遍历找到这两个元素curr1和curr2,同时存储这两个元素的前驱元素pre1和pre2,然后大换血。

public static Link SwitchPoints(Link head, Link p, Link q)
{
if (p == head || q == head)
throw new Exception(“No exchange with head”);
if (p == q)
return head;
//find p and q in the link
Link curr = head;
Link curr1 = p;
Link curr2 = q;
Link pre1 = null;
Link pre2 = null;

int count = 0;
while (curr != null)
{
if (curr.Next == p)
{
pre1 = curr;
count++;
if (count == 2)
break;
}
else if (curr.Next == q)
{
pre2 = curr;
count++;
if (count == 2)
break;
}
curr = curr.Next;
}
curr = curr1.Next;
pre1.Next = curr2;
curr1.Next = curr2.Next;
pre2.Next = curr1;
curr2.Next = curr;
return head;
}
注意特例,如果相同元素,就没有必要交换;如果有一个是表头,就不交换。


6、按自然序列对数字数组进行排序和按自然序列对字符串数组进行排序

import java.util.Arrays;

public class SortArray {

/**
* 按自然序列对数字数组进行排序
*/
public void sortIntArray() {

int[] arrayToSort = new int[] { 48, 5, 89, 80, 81, 23, 45, 16, 2 };

Arrays.sort(arrayToSort);

for (int i = 0; i < arrayToSort.length; i++) {
System.out.println(arrayToSort[i]);
}

}

/**
* 按自然序列对字符串数组进行排序
*/
public void sortStringArray() {

String[] arrayToSort = new String[] { “Oscar”, “Charlie”, “Ryan”,
“Adam”, “David” };

Arrays.sort(arrayToSort);

for (int i = 0; i < arrayToSort.length; i++) {
System.out.println(arrayToSort[i]);
}
}

public static void main(String[] args) {
SortArray main = new SortArray();
main.sortIntArray();
main.sortStringArray();
}
}

运行结果:

2
5
16
23
45
48
80
81
89
Adam
Charlie
David
Oscar
Ryan

注:

反自然序列:Arrays.sort(arrayToSort, Collections.reverseOrder());


7、输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数

public class num2
{
public static void main(String[] args)
{
int ywzm,space,num,other;
ywzm=space=num=other=0;
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String str = null;
try {
str = br.readLine();
} catch (IOException ex) {
Logger.getLogger(num2.class.getName()).log(Level.SEVERE, null, ex);
}
char[] carr=str.toCharArray();
for (int i = 0; i < carr.length; i++) {
if((carr>=’0′)&&(carr<=’9′))
num++;
else if((carr>=’A'&&carr=’a'&&carr<=’z'))
ywzm++;
else if(carr==’ ‘)
space++;
else
other++;
}
System.out.println(“英文字母个数:”+ywzm+”\t空格个数”+space+”\t数字个数”+num+”\t其他字符个数:”+other);
}
}


8、伪造硬币问题

给你一个装有n个硬币的袋子。n个硬币中有一个是伪造的。你的任务是找出这个伪造的硬币。为了帮助你完成这一任务,将提供一台可用来比较两组硬币重量的仪器,利用这台仪器,可以知道两组硬币的重量是否相同。试用分治法的思想写出解决问题的算法,并计算其时间复杂度。

#include<stdlib.h>  
#include<stdio.h>  
#include<time.h>
#define N 6
void setWrong(int *coin,int n)
{
int i;
int ran;
for(i=0;i<n;i++)
coin[i]=1;
srand(time(0));  //随机数种子被初始化时
ran=rand()%n;
printf("jia%d\n",ran);
coin[ran]=0;
}

/*
param coin 表示需要找假硬币的数组;
param astart 前一个分组的开始;
param bstart 后一个分组的开始;
param n 每个分组的长度;
*/
int compare(int *coin,int astart,int bstart,int n)
{
int asum=0;
int bsum=0;
int i;
for(i=astart;i<astart+n;i++)
asum+=coin[i];
for(i=bstart;i<bstart+n;i++)
bsum+=coin[i];
if(asum<bsum) return -1;
if(asum==bsum) return 0;
if(asum>bsum) return 1;
}

int find(int *coin,int start,int n)
{
if(n==1)
{
printf("第%d个是假币",start);
return start;
}
if((n%2)==0)
{
if(compare(coin,start,n/2,n/2)==-1) find(coin,start,n/2);
else if(compare(coin,start,n/2,n/2)==0) return -1;
else find(coin,n/2,n/2);
}
else
{
if(compare(coin,start,start+(n-1)/2,(n-1)/2)==-1) find(coin,start,(n-1)/2);
else if(compare(coin,start,start+(n-1)/2,(n-1)/2)==0) find(coin,start+n-1,1);
else find(coin,start+(n-1)/2,(n-1)/2);
}
}

void main()
{
int a
;
setWrong(a,N);
printf("%d",find(a,0,N));
}


9、Python实现java或者.net的getHashCode()函数

hashCode在.net和java中应用很普遍,但是python没有内置的getHashcode函数。

如下是java版本getHashcode的python实现

# -*- coding:utf-8 -*-
def convert_n_bytes(n, b):
bits = b*8
return (n + 2**(bits-1)) % 2**bits - 2**(bits-1)

def convert_4_bytes(n):
return convert_n_bytes(n, 4)

def getHashCode(s):
h = 0
n = len(s)
for i, c in enumerate(s):
h = h + ord(c)*31**(n-1-i)
return convert_4_bytes(h)

if __name__ == '__main__':
print getHashCode('http://outofmemory.cn/')
print getHashCode('http://outofmemory.cn/code-snippet/2311/C-rumenjiaocheng-c-multithreading-process-course')
print getHashCode('http://outofmemory.cn/code-snippet/2321/C-rumenjiaocheng-usage-arrow-unsafe-code-block/')
print getHashCode('http://outofmemory.cn/code-snippet/2322/mysql-achieve-sql-server-with-lock')
print getHashCode('http://outofmemory.cn/')
print getHashCode('http://outofmemory.cn/code-snippet/2324/java-unit-test-usage-jMockit-mock-jingtailei')


10、删除单链表中重复的元素

用Hashtable辅助,遍历一遍单链表就能搞定。

实践中发现,curr从表头开始,每次判断下一个元素curr.Netx是否重复,如果重复直接使用curr.Next = curr.Next.Next; 就可以删除重复元素——这是最好的算法。唯一的例外就是表尾,所以到达表尾,就break跳出while循环。

public static Link DeleteDuplexElements(Link head)
{
Hashtable ht = new Hashtable();
Link curr = head;
while (curr != null)
{
if (curr.Next == null)
{
break;
}
if (ht[curr.Next.Data] != null)
{
curr.Next = curr.Next.Next;
}
else
{
ht[curr.Next.Data] = “”;
}
curr = curr.Next;
}
return head;
}


结语:

单链表只有一个向前指针Next,所以要使用1-2个额外变量来存储当前元素的前一个或后一个指针。

尽量用while循环而不要用for循环,来进行遍历。

哇塞,我就是不用指针,照样能“修改地址”,达到和C++同样的效果,虽然很烦~

遍历的时候,不要在while循环中head=head.Next;这样会改变原先的数据结构。我们要这么写:Link curr=head;然后curr=curr.Next;

有时我们需要临时把环切开,有时我们需要临时把单链表首尾相连成一个环。

究竟是玩curr还是curr.Next,根据不同题目而各有用武之地,没有定论,不必强求。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  面试题 编程