关于数组的一些面试题目及答案

1.给你一个数组,求一个k值,使得前k个数的方差 + 后面n-k个数的方差最小 ,时间复杂度可以到O(n)。

根据方差公式D(X)=E(x^2)-[E(X)]^2

def minVariance(arr):
    sum=0
    square_sum=0
    length=len(arr)
    left_var=[0]*length
    right_var=[0]*length
  #从左到右求每一段的方差
for i in range(length): sum+=arr[i] square_sum+=arr[i]*arr[i] left_var[i]=square_sum/(i+1)-(sum/(i+1))**2

sum = 0 square_sum = 0
#从右到左求每一段的方差
for j in range(length-1,-1,-1): sum+=arr[j] square_sum += arr[j] * arr[j] right_var[j] = square_sum / (length-j) - (sum / (length-j)) ** 2
  #二者合并,找出方差最小的两断 index
=0 variance=left_var[0]+right_var[0] for k in range(length-1): if left_var[k]+right_var[k+1]<variance: variance=left_var[k]+right_var[k] index=k+1 return index

 

2.给你一个只由0和1组成的字符串,找一个最长的子串,要求这个子串里面0和1的数目相等。     时间复杂度可以到O(n) 

这样一种巧妙的解法:定义一个数据B[N], B[i]表示从A[0...i]中 num_of_0 - num_of_1,0的个数与1的个数的差。 那么如果arr[i] ~ arr[j]是符合条件的子串,一定有 B[i] == B[j],因为中间的部分0、1个数相等,相减等于0。 只需要扫一遍A[N]就能把B[N]构造出来了。

def findMaxEqualSequence(arr):
    count=[0,0]
    B=[0]*len(arr)
    dict_num={}
    curlen=0
    maxlen=0
    for i in range(len(arr)):
        count[arr[i]]+=1
     #数组B保存到当前i下标这一段中0出现的次数与1出现的次数之差 B[i]=count[0]-count[1]
     #如果到当前下标差值等于0,说明从开始到现在两者出现次数是一样的,当前下标+1就是满足要求最长子串的长度,直接continue下一个就行了
if B[i]==0: maxlen=i+1
       continue
     #将差值第一次出现都保存在字典里面,以后每次计算一个差值都访问一下字典,如果字典中有,说明字典保存的下标到当前下标这一段,出现0与1
#的个数是相等的,然后计算两者下标之差,与maxlen做比较即可。 if dict_num.__contains__(B[i]): curlen=i-dict_num[B[i]] if curlen>maxlen: maxlen=curlen
#字典中没有说明该差值第一次出现,就记录在字典中
else: dict_num[B[i]]=i return maxlen

 3.给你一个数组,求一个数组的最大值和次大值

def getMaxAndNextMax(arr):
    max_val=arr[0]
    next_val=arr[0]
    for k in arr:
        if k>max_val:
            next_val=max_val
            max_val=k
        elif k>next_val:
            next_val=k

    return(max_val,next_val)
        
    
a=[-2.5,4,300,3,1000,8,100]
print(getMaxAndNextMax(a))

 4.给定一个n个整型元素的数组a,其中有一个元素出现次数超过n / 2,求这个元素。据说是百度的一道题

方法一:对数组进行排序,因为一个元素已经超过了一半,则中间位置的元素就必为该元素。

方法二:火拼方法。

来看这样一个例子:

5 1 5 4 1 1 3 1 2 1 1

一共11个数字,其中1一共出现了6次。那么如何快速的找到这个6呢?我们来考虑这样一个现实生活中的例子:有一群人在打群架,他们每个人有一个编号,代表自己所处的势力,现在这一群人按照顺序依次往广场中央走,如果广场内现在有和自己不是一个势力的人,那么他就和其中一个同归于尽,问,最后哪一个势力的人会获胜?我们按照这个意思,再来看一下刚才这个例子:

1)势力5的一个人走进广场中央,现在广场中央有一个人,势力是5

2)势力1的一个人走进广场中央,他发现广场中央有一个势力是5的人,于是同归于尽,现在广场上没有人

3)势力5的一个人走进广场中央,现在广场中央有一个人,势力是5

4)势力4的一个人走进广场中央,他发现广场中央有一个势力是5的人,于是同归于尽,现在广场上没有人

5)势力1的一个人走进广场中央,现在广场有一个人,势力是1

6)势力1的一个人走进广场中央,现在广场有两个人,势力是2

……

可以发现,每一次火拼,势力最大(也就是出现次数最多的那个数字)的那个每次最多只会死亡一个。而火拼最多会进行N/2次,出现频率最高的那个数字最多只会损失N/2个,而题上告诉我们出现次数已经超过了一半,因此广场上剩下的那个团伙的编号必然是出现次数做多的那个!这样一来,代码就非常好写了。

def getAppearMoreThanHalf(arr):
    curVal=arr[0]
    count=1
    for i in range(1,len(arr)):
        if count==0:
            curVal=arr[i]
            count=1
            continue
        if arr[i]==curVal:
            count+=1
        else:
            count-=1 
    return curVal        
    
a=[3,5,7,7,7]
print(getAppearMoreThanHalf(a))

5.求数组中元素的最短距离

题目:给定一个含有n个元素的数组,找出数组中的两个元素X和Y使得abs(x-y)最小

解题思路:先排序,然后遍历元素。

6.求两个有序数组的共同元素

充分利用数组有序的性质,用两个指针i和j分别指向a和b,比较a[i]和b[j],根据比较结果移动指针,则有如下三种情况

1. a[i] < b[j],则i增加1,继续比较

2. a[i] == b[j],则i和j皆加1,继续比较

3. a[i] < b[j],则j加1,继续比较

重复以上过程直到i或j到达数组末尾。

小小总结一下,对于在数组中进行查找的问题,可以分如下两种情况处理

1. 如果给定的数组有序,那么首先应该想到Binary Search,所需O(logn)

2. 如果给定的数组无序,那么首先应该想到对数组进行排序,很多排序算法都能在O(nlogn)时间内对数组进行排序,然后再使用二分搜索,总的时间复杂度仍是O(nlogn)。

如果能做到以上两点,大多数关于数组的查找问题,都能迎刃而解。

7.求数组中满足给定和的数对

题目:给定两个有序整型数组a和b,各有n个元素,求两个数组中满足给定和的数对,即对a中元素i和b中元素j,满足i + j = d(d已知)

解析:两个指针i和j分别指向数组的首尾,然后从两端同时向中间遍历。

// 找出满足给定和的数对
void FixedSum(int* a, int* b, int n, int d)
{
    for (int i = 0, j = n - 1; i < n && j >= 0)
    {
        if (a[i] + b[j] < d)
            ++i ;
        else if (a[i] + b[j] == d)
        {
            cout << a[i] << ", " << b[j] << endl ;
            ++i ;
            --j ;
        }
        else // a[i] + b[j] > d
            --j ;
    }
}

8.字符串逆序

题目:给定一个含有n个元素的字符数组a,将其原地逆序(不能额外开辟空间)。

def strReverse(s):
    left=0
    right=len(s)-1
    while left<right:
        s[left],s[right]=s[right],s[left]
        left+=1
        right-=1    
    return s    

s="abcde"
print(strReverse(s))

9.数组元素重排问题

给定含有n个元素的整型数组a,其中包括0元素和非0元素,对数组进行排序,要求:

1. 排序后所有0元素在前,所有非零元素在后,且非零元素排序前后相对位置不变

2. 不能使用额外存储空间

例子如下

输入 0, 3, 0, 2, 1, 0, 0

输出 0, 0, 0, 0, 3, 2, 1

解析:从尾部开始设置两个指针,last指针指向后面第一个出现0的位置,first指向last前面的第一个非0元素,如果first是非0,则将值赋给last,然后last++,first++;如果first指向0,则继续前进first++。

def Arrange(arr):
    length=len(arr)
    first=length-1
    last=length-1
#last从后面找到第一个0元素位置 if arr[last]!=0: while last>=0 and arr[last]!=0: last-=1 if last<0: return first=last-1 #这个时候开始遍历走 while first>=0: if arr[first]!=0: arr[first],arr[last]=arr[last],arr[first] first-=1 last-=1 else: first-=1 return arr a=[6,0,3,0,2,1,0,0] print(Arrange(a))

10.找出绝对值最小的元素

题目:给定一个有序整数序列(非递减序),可能包含负数,找出其中绝对值最小的元素,比如给定序列 -5, -3, -1, 2, 8 则返回1。

解析

  • 如果给定的序列中所有的数都是正数,那么数组的第一个元素即是结果。
  • 如果给定的序列中所有的数都是负数,那么数组的最后一个元素即是结果。
  • 如果给定的序列中既有正数又有负数,那么绝对值得最小值一定出现在正数和负数的连接处
def findAbsoluteMinVal(arr):
    if arr[0]>0:
        return arr[0]
    if arr[len(arr)-1]<0:
        return arr[len(arr)-1]
    for i in range(1,len(arr)):
        if arr[i]>0:
            return arr[i] if abs(arr[i-1])>arr[i] else abs(arr[i-1])

 11.two sum(leetcode题目一)

     未排序数组,找出两个元素值等于target值,并返回下标,小的下标在前面。

def twoSum(self, nums, target):
        if len(nums)<1:
            return
        dict={}
        for i in range(len(nums)):
            if target-nums[i] in dict:
                return (dict[target-nums[i]],i)
            else:
                dict[nums[i]]=i
原文地址:https://www.cnblogs.com/gczr/p/8334459.html