您的位置:首页 > 其它

笔试

2015-10-01 10:39 176 查看
算法一定要掌握快排 http://blog.csdn.net/morewindows/article/details/6684558  挖坑很好理解

//快速排序
void quick_sort(int s[], int l, int r)
{
if (l < r)
{
//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
int i = l, j = r, x = s[l];
while (i < j)
{
while(i < j && s[j] >= x) // 从右向左找第一个小于x的数
j--;
if(i < j)
s[i++] = s[j];

while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
i++;
if(i < j)
s[j--] = s[i];
}
s[i] = x;
quick_sort(s, l, i - 1); // 递归调用
quick_sort(s, i + 1, r);
}
}

全排列一定要掌握,很多题目都要用到  http://blog.chinaunix.net/uid-1844931-id-3341657.html  http://blog.csdn.net/e3399/article/details/7543861

如果不要最小字典序使用递归比较容易理解,如果要求最小字典序用到非递归程序

递归程序:

void recurPermutation(int *arr, int n, int i)
{
if(i==n-1) {
printArray(arr, n);
}
for(int j=i; j<n; j++) {
//if(IsSap(arr,i,j)){//去重
swap(arr, i, j);
recurPermutation(arr, n, i+1);
swap(arr, i, j);
/}
}
}


去重递归://在递归的时候加一个判断即可[start,end)都不和end相等

//在pszStr数组中,[nBegin,nEnd)中是否有数字与下标为nEnd的数字相等
bool IsSwap(char *pszStr, int nBegin, int nEnd)
{
for (int i = nBegin; i < nEnd; i++)
if (pszStr[i] == pszStr[nEnd])
return false;
return true;
}


非递归程序:会按照最小字典序依次输出
//求取全排列,打印结果
void combination(int a[],int length)
{
if(length<2) return;

bool end=false;
while(true) {
print(a,length);

int i,j;
//找到不符合趋势的元素的下标i
for(i=length-2; i>=0; --i) {
if(a[i]<a[i+1]) break;
else if(i==0) return;
}

for(j=length-1; j>i; --j) {
if(a[j]>a[i]) break;
}

swap(a,i,j);
reverse(a,i+1,length-1); //反转后面的,这里比较难理解一点
}
}

next数组是什么?  KMP http://www.cnblogs.com/c-cloud/p/3224788.html

求子集,利用二进制递增,所有的都会遍历到,如1,10,11,100,101,110,111等,所以可以利用二进制递增去求出所有的子集组合

n个人围成一圈喊道m的退出,Josephus问题 

//函数接收n和m,返回最后出圈的是第几个人
/*e.g.       yuesefu(5,2)=3
yuesefu(2,100)=1*/
int   yuesefu(int   n,int   m)
{
int   i,r=0;
for   (i=2;i <=n;i++)   r=(r+m)%i;
return   r+1;
}


动态规划

比如求最大递增序列 http://www.cnblogs.com/lonelycatcher/archive/2011/07/28/2119123.html

思路用一个数组f来存放对应的最大递增数量,比如f[3]代表以第4个数为结尾的最大递增数据,因为前面的f存放的都是以自己结束的最大递增数据,所以可以找到最大的那个值加1就等于f[3]。。。描述起来咋这么困难

public void lis(float[] L)
{
int n = L.length;
int[] f = new int
;//用于存放f(i)值;
f[0]=1;//以第a1为末元素的最长递增子序列长度为1;
for(int i = 1;i<n;i++)//循环n-1次
{
f[i]=1;//f[i]的最小值为1;
for(int j=0;j<i;j++)//循环i 次
{
if(L[j]<L[i]&&f[j]>f[i]-1)   //这里很关键,现在还难理解,多想几次
f[i]=f[j]+1;//更新f[i]的值。
}
}
System.out.println(f[n-1]);
}
小米试卷: http://m.mrnum.com/ZhaoPinBiShiTi/53297-2.html  数组乘积题目

解答:数组a
,第k个的乘积是分为两部分,一部分是左侧部分a[0]-a[k-1],一部分是右侧部分a[k+1]-a[n-1]
所以可以先将左侧的乘积保存到输出数组中,输出数组现在少了右边部分的乘积,从a[0]=a[n-1]*a[n-2]*....a[1]可以看出a[0]从最右边向左边依次相乘时刚好是输出数组的右侧部分,将右侧部分乘到输出数组对应位中就可以很快的得出最后的输出数组了
比如a[0]  a[1] a[2] a[3],输出为数组b[3],先将b[1]=a[0] b[2]=b[1]*a[1] b[3]=b[2]*a[2]现在只保存了左侧的乘积
再来b[3]=b[3],b[2]=b[2]*a[3],b[1]=b[1]*a[2]*a[3],中间利用b[0]作为中介
在一个长度为n的整形数组a里,除了三个数字只出现一次外,其他的数字都出现了2次。请写程序输出任意一个只出现一次的数字,程序时间和空间复杂度越小越好。

解答:一个关键点就是a^a=0;a^0=a;此外最关键的是有三个数字只出现过一次,a,b,c,可以验证a^b^c得到结果最右边位为1的那一位必定只属于a,b,c中的一个数,因为如果是两个都有那一位亦或以后就会为0,不可能为1,这样就可以把a,b,c三个数分为两组

朋友圈题目是一个并查集问题  很好理解的博客是http://blog.csdn.net/dellaserss/article/details/7724401,给的程序实际上还是可以优化的,按照小米试卷上的答案

int set[10001];
inline int find(int x) //带路径优化的并查集查找算法
{
  int i , j , r;
  r = x;
  while(set[r] != r)
    r = set[r];
  i = x;
  while(i != r)
  {
    j = set[i];
    set[i] = r;
    i = j;
  }
 return r;
}
inline void merge(int x , int y) //优化的并查集归并算法
{
  int t = find(x);
  int h = find(y);
//统一以最小的为顶端会减少find函数中替换头操作
  if(t < h)
    set[h] = t;
  else
    set[t] = h;
}
int friends(int n , int m , int* r[])
{
  int i , count;
  for(i = 1 ; i <= n ; ++i) //初始化并查集,各点为孤立点,分支数为n
    set[i] = i;
  for(i = 0 ; i < m ; ++i)
    merge(r[i][0] , r[i][1]);
  count = 0;
  for(i = 1 ; i <= n ; ++i)
  {
    if(set[i] == i)
    ++count;
  }
  return count;
}


现在笔试都要求写出完整程序,可是没有编译环境啊,平时头部等等都是用的系统自带的,记不住,下面的死记硬背一下

1.C++

#include<iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
cout << "hello"<< endl;
getchar();
return 0;
}

2.Java

public static void main(String[] args)
{
System.out.print("hello");
System.out.println();
}

3.C#

算法编程题目

1.美团面试要我写出快速排序法,递归等,都不会

递归题目int getNumber(int n,int k)  从1-9选取k个数组成n的值,问有多少种组合。。。当时不会,所以挂掉了

晚上想了一下原来这么简单,oh,no,因为是递归,有些条件一定没有结果,所以可以加一些限制条件,如n>45和k>9时都为0来减少递归规模

public class ProbabilityTest {
public static void main(String[] args) {
int n = 45;
int k = 9;
int num = getNumber(45, 9);
System.out.println(num);
}

public static int getNumber(int n, int k) {
if (n > 45 || k > 9)
return 0;
return getNumber(1, n, k);
}

public static int getNumber(int min, int n, int k) {
if (k <= 0)
return 0;
else if (k == 1) {
if (n >= min && n <= 9)
return 1;
else
return 0;
} else {
int sum = 0;
for (int i = min; i <= (10 - k); i++) {
sum += getNumber(min + 1, n - min, k - 1);
}
return sum;
}
}
}


2.寻找超过一半的变量   如果是整数排完序那个数一定是中间的那个数 ,相似题目shool[]数组有一半来自某大学,最好的算法找出这个大学

快速排序法虽然很好,但是实现麻烦,有一个最好的算法

// 假设最多的那个大学超过一半
// 结果一定是最后一个让num为1的那个学校
public static String findMaxScool(String[] schools) {
if (schools.length < 1)
return null;
String result = schools[0];
int num = 0;
for (String school : schools) {
if (num == 0) {
num = 1;
result = school;
} else if (result == school) {
num++;
} else if (result != school) {
num--;
}
}
return result;
}


Android笔试:

1.<style name="a" parent="@style/TextApprenace.Medium">  经验证必须要同时定义TextAppearance和TextAppearance.Medium才能通过编译

2.finishActivity   用法比如A startActivityForResult(b,requestCode)启动了B,一段时间后A收到了消息或者子线程主动要关闭B,则调用finishActivity(B)可以成功关闭B


Intent intent = new Intent(this, Activity1.class);
startActivityForResult(intent, 1);
new Handler().postDelayed(new Runnable() {
public void run() {
finishActivity(1);
}
}, 5000);

上述代码启动了Activity1的5s以后会被关闭

finishActivityFromChild(Activity child,int requestCode)

finishFromChild(Activity child)

测试这两个函数都是结束掉当前的activity很郁闷,感觉作用和finish()没有区别

finishAffinity();  结束activity本身和它前面所有的activity

按下Home键以后,系统会查找哪类Activity?不知道。。。intengFilter里面的action和category是什么样的

堆栈寄存器

Android虚拟机和Java虚拟机的区别   http://blog.csdn.net/aeolus1019/article/details/8123671

Java判断大端和小端  Java.nio.ByteOrder   http://blog.chinaunix.net/uid-1844931-id-3022904.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: