zoukankan      html  css  js  c++  java
  • 【剑指Offer】俯视50题之31

    面试题31连续子数组的最大和 

    面试题32从1到n整数中1出现的次数 

    面试题33把数组排成最小的数 

    面试题34丑数 

    面试题35第一个仅仅出现一次的字符 

    面试题36数组中的逆序对

    面试题37两个链表的第一个公共结点 

    面试题38数字在排序数组中出现的次数 

    面试题39二叉树的深度 

    面试题40数组中仅仅出现一次的数字 

    /*******************************************************/

    面试题31连续子数组的最大和 ,输入一个数组。数组里面有正数,也有负数。

    求连续数的最大值

    实现例如以下:

    int MaxSum(int num[], int length)
    {
    	int CurrentSum = 0;
    	int iResult = 0x80000000;
    	
    	if (num == NULL || length < 0)
    	{
    		return 0;/* invalid */
    	}
    	
    	for (int i = 0; i < length; i++)
    	{
    		
    		if (CurrentSum <= 0)
    		{
    			CurrentSum = num[i];
    		}
    		else
    		{
    			CurrentSum += num[i];
    		}
    
    		if (CurrentSum > iResult)
    			iResult = CurrentSum;
    	}
    	return iResult;
    }

    面试题32从1到n整数中1出现的次数 ,输入一个N,求1到N全部的整数中1出现的次数

    实现例如以下:

    #include <iostream>
    
    int CountNum(int n)
    {
    	int iCurrentNum = 0;/* 当前位的数 */
    	int iNTemp = n;
    	int iResult = 0;
    	int iBase = 1;  /* 个位 */
    	int iRemain = 0;
    
    	if (n <= 0)
    	{
    		return 0;
    	}
    	
    	while (iNTemp > 0)
    	{
    		iCurrentNum = iNTemp % 10;
    		iNTemp = iNTemp/10;
    
    		if (iCurrentNum > 1)
    		{
    			iResult+= (iNTemp + 1)*iBase;
    		}
    		else if (iCurrentNum == 1)
    		{
    			iResult+= (iNTemp)*iBase + iRemain + 1;
    		}
    		else if (iCurrentNum == 0)
    		{
    			
    			iResult+= (iNTemp)*iBase;
    		}
    
    		
    		iRemain += iCurrentNum*iBase; /* 先计算剩余数大小*/
    		iBase = iBase*10; /**然后计算下次base位*/ 
    	}
    
    	return iResult;
    }
    
    int main()
    {
    	printf("%d
    ",CountNum(11));
    }
    


    面试题33把数组排成最小的数 

    实现例如以下:

    #include <iostream>
    #define MAX_NUM_LENGTH 10
    
    int compare(const void *str1, const void *str2)
    {
    	char str1Temp[MAX_NUM_LENGTH*2 +1];
    	char str2Temp[MAX_NUM_LENGTH*2 +1];
    
    	strcpy(str1Temp, (const char*)str1);
    	strcat(str1Temp, (const char*)str2);
    	
    	strcpy(str2Temp, (const char*)str2);
    	strcat(str2Temp, (const char*)str1);
    
    	return strcmp(str1Temp,str2Temp);
    	
    }
    void GetMinNum(int num[], int length)
    {
    	char **numStr = (char **)malloc(length + 1);
    	for (int i = 0; i < length; i++)
    	{
    		numStr[i] = (char *)malloc(MAX_NUM_LENGTH +1);
    		sprintf(numStr[i],"%d",num[i]);
    	}
    	qsort(numStr,length,sizeof(char *),compare);
    
    	for (int i = 0; i < length; i++)
    	{
    		printf("%s",numStr[i]);
    	}
    
        /* 释放内存 */
    	for (int i = 0; i < length; i++)
    	{
    		free(numStr[i]);
    	}
    	free(numStr);
    
    }
    
    int main()
    {
    	int num[] = {1,234,341};
    	GetMinNum(num, 3);
    }
    


    面试题34丑数 

    实现例如以下:

    #include <iostream>
    #define MAX_NUM_LENGTH 10
    
    int min(int a, int b, int c)
    {
    	int min = (a>b)?b:a;
    	min = (min > c)?

    c:min; return min; } /* 仅仅能被2、3、5整除的 */ int GetUglyNum(int n) { /* 创建一个n个元素的数组 */ int UglyNum[n]; int p2 = 0; int p3 = 0; int p5 = 0; int NextIndex = 1; UglyNum[0] = 1; while(NextIndex < n) { UglyNum[NextIndex] = min(UglyNum[p2]*2, UglyNum[p3]*3 ,UglyNum[p5]*5); while(UglyNum[p2]*2 <= UglyNum[NextIndex]) { p2++; } while(UglyNum[p3]*3 <= UglyNum[NextIndex]) { p3++; } while(UglyNum[p5]*5 <= UglyNum[NextIndex]) { p5++; } NextIndex++; } return UglyNum[NextIndex - 1]; } int main() { printf("%d ",GetUglyNum(3)); }



    面试题35第一个仅仅出现一次的字符 

    实现例如以下:

    #include <iostream>
    #define VOS_OK  0
    #define VOS_ERR 1
    
    
    /* 仅仅能被2、3、5整除的 */
    int GetFirstChar(char *str, char *result)
    {
    	unsigned int hashNum[256] = {0};
    	char *p;
    	
    	if (str == NULL)
    	{
    		return VOS_ERR;
    	}
    	
    	p = str;
    	while(*p != '')
    	{
    		hashNum[*p]++;
    		p++;
    	}
    
    	p = str;
    	while(*p!= '')
    	{
    		if (hashNum[*p] == 1)
    		{
    			*result = *p;
    			return VOS_OK;
    		}
    		p++;
    	}
    	return VOS_ERR;
    
    }
    
    int main()
    {
    	char iChar;
    	if (VOS_OK == GetFirstChar("aabcddb", &iChar))
    	{
    		printf("%c
    ",iChar);
    	}
    	else
    	{
    		printf("Error!"); 
    	} 	
    }
    


    面试题36数组中的逆序对

    实现例如以下:

    /* 求数组中的逆序对 */
    #include <iostream>
    #define VOS_OK  0
    #define VOS_ERR 1
    int Merge(int *numA, int begin,int mid, int end)
    {
    	int startA = begin;
    	int startB = mid + 1;
    	int *numB = (int *)malloc(sizeof(int)*(end + 1));
    	int currentIndex = 0;
    	long long result = 0;
    
    	if (numA == NULL || begin > mid || mid > end)/* 其余异常函数调用处保证 */
    	{
    		return 0;
    	}
    
    	while (startA <=mid && startB <= end)
    	{
    		if (numA[startA] <= numA[startB])
    		{
    			numB[currentIndex] = numA[startA++];
    		}
    		else
    		{
    			numB[currentIndex] = numA[startB++];
    			/* 前面的大于后面的,则前数组之后的元素也大于该元素 */
    			result += mid - startA + 1;
    		}
    
    
    		currentIndex++;
    	}
    
    	while (startA <= mid)
    	{
    		numB[currentIndex++] = numA[startA++];
    	}
    
    	while (startB <= end)
    	{
    		numB[currentIndex++] = numA[startB++];
    	}
    
        for (int i = begin; i <= end; i++)
        {
        	numA[i] = numB[i];
        }
        free(numB);
    
        return result;
    	
    }
    
    int MergeSort(int *num, int start, int end)
    {
    	int result = 0;
    	int mid;
    	if (num == NULL || start >= end) /* 注意start == end 的时候*/
    	{
    		return 0;		
    	}
    	
    	mid = (start + end)>>1;
    	result = MergeSort(num, start, mid) + MergeSort(num, mid +1, end);
    	result += Merge(num,start,mid,end);
    
    	return result;
    
    }
    
    int main()
    {
    	int num[]={2,1,3,5,6};
    
    	printf("%d
    ",MergeSort(num, 0, 4));	
    }
    


    面试题37两个链表的第一个公共结点 

    实现例如以下:

      1)暴力法

             每次遍历链表A,然后将链表A中当前结点在链表B中查找。假设找到则停止查找,返回。

      2)空间换取时间

           将两个链表都入栈,然后从最后一个结点開始比較。直到不相等为止。
      3)同一时候向后查找

       先遍历链表A得长度lengthA。再遍历链表B得长度lengthB

       假如A比B长n。则A先走n步,假如B比A长n,则B先走n步。

       然后同一时候向后走,直到第一个相等的结点


    面试题38数字在排序数组中出现的次数 

    有两种思路:利用二分查找法,找到该数中间出现的位置,然后分别向前后遍历同样数,可得到该数出现的次数

         利用二分查找法,找打该数最左边及最右边出现的位置。然后就能够求得该数出现的次数

    左右查询实现例如以下:

    #include <iostream>
    int MaxSum(int num[], int length, int value)
    {
    	int iResult = 0;
    	int i = 0;
    	int j = length - 1;
    	int mid;
    	int k;
    
    	while(i <= j )
    	{
    		mid = (i + j)>>1;
    		if (num[mid] > value)
    		{
    			j= mid - 1;
    		}
    		else if (num[mid] < value)
    		{
    			i = mid + 1;
    		}
    		else
    		{
    			/* 向左查询*/
    			k = mid-1;
    			while (k >= i &&(num[k] == value))
    			{
    				k--;
    				iResult++;
    			}
    			/* 向右查询*/
    			k = mid+1;
    			while (k <= j &&(num[k] == value))
    			{	
    				k++;
    				iResult++;
    			}
    			printf("================");
    			return iResult + 1;
    		}
    	}
    
    	return iResult;
    }
    
    int main()
    {
    	int num[]={2,2,2,2,5,5,6,6};
    
    	printf("%d
    ",MaxSum(num, 8, 2) );
    	getchar();
    }

    第二种实现方法:

    #include <iostream>
    int GetFirstK(int num[], int length, int value)
    {
    	int mid;
    	int i = 0;
    	int j = length - 1;
    	
    	if (num == NULL)
    	{
    		return 0;
    	}
    
    	while (i <= j)
    	{
    		mid = (i + j)>>1;
    
    		if (num[mid] > value)
    		{
    			j = mid - 1;
    		}
    		else if (num[mid] < value)
    		{
    			i = mid + 1;
    		}
    		else
    		{
    			if (mid -1 >= 0 && (num[mid - 1] == value))
    			{
    				j = mid - 1;
    			}
    			else
    			{
    				return mid;
    			}
    		}
    	}
    
    	return 0;
    }
    
    int GetLastK(int num[], int length, int value)
    {
    	int mid;
    	int i = 0;
    	int j = length - 1;
    	
    	if (num == NULL)
    	{
    		return 0;
    	}
    
    	while (i <= j)
    	{
    		mid = (i + j)>>1;
    
    		if (num[mid] > value)
    		{
    			j = mid - 1;
    		}
    		else if (num[mid] < value)
    		{
    			i = mid + 1;
    		}
    		else
    		{
    			if (mid + 1 <= j && (num[mid + 1] == value))
    			{
    				i = mid + 1;
    			}
    			else
    			{
    				return mid;
    			}
    		}
    	}
    
    	return 0;
    }
    
    int main()
    {
    	int num[]={2,2,2,2,5,5,6,6};
    
    	printf("%d
    ",GetLastK(num, 8, 2) - GetFirstK(num, 8, 2) + 1);
    	getchar();
    }

    面试题39二叉树的深度 

    实现例如以下:

    int DepthTree(BinaryNode *root)
    {
    	int leftDepth = 0;
    	int rightDepth = 0;
    	
    	if (root == NULL)
    	{
    		return 0;
    	}
    
    	leftDepth = DepthTree(root->lchild);
    	rightDepth = DepthTree(root->rchild);
    
    	retrun (leftDepth > rightDepth)? (leftDepth + 1):(rightDepth + 1);	
    }

    扩展题目:推断一个树是否是平衡二叉树

    实现例如以下:

    bool IsBlanceTree(BinaryNode *root, int *depth)
    {
    	int leftDepth = 0;
    	int rightDepth = 0;
    	int diff;
    	
    	if (root == NULL)
    	{
    		return true;
    	}
    
    	leftDepth = DepthTree(root->lchild);
    	rightDepth = DepthTree(root->rchild);
    
    	if (IsBlanceTree(root->lchild, &leftDepth)
    		&&IsBlanceTree(root->rchild, &rightDepth))
    	{
    		diff = leftDepth - rightDepth;
    		if (diff < 1 && diff > -1)
    		{
    			*depth = (leftDepth > rightDepth)? (leftDepth + 1):(rightDepth + 1);
    			return true;
    		}
    	}
    	
    	retrun false;	
    }
    

    面试题40数组中仅仅出现一次的数字 :给一个数组,数组中有两个数仅仅出现一次。其余数出现两次,求这两个数

    思路:将数组分成两组,分别异或去重。怎样分组呢?分组依据异或之后。最后一位二进制值为1的位分组。对数组一进行异或最后得一个数。对数组二异或。最后得还有一个数。

    则最后得到的两个数是所求的数。

    实现例如以下:

    int FindFirstBitIsOne(int resultOR)
    {
    	for (int i = 0; i < 32; i++)
    	{
    		if (resultOR & (1 << i))
    		{
    			return i;
    		}
    	}
    	return 0;
    		
    }
    
    int IsBitOne(int data, int indexOfOne)
    {
    	return data & (1<<indexOfOne);
    
    }
    void FindNumsAppearOnce(int data[],int length,int *num1,int num2)
    {
    	if (data == NULL || length < 2)
    	{
    		return;
    	}
    	int resultOR = 0;
    	for (int i = 0; i < length; i++)
    	{
    		resultOR ^=data[i];
    	}
        
    	int indexOfOne = FindFirstBitIsOne(resultOR);
    	
    	for (int j = 0; j < length; j++)
    	{
    			if (IsBitOne(data[j], indexOfOne))
    			{
    					*num1 ^=data[j];
    			}
    			else
    			{
    					*num2^=data[j];
    			}
    	}
    
    }





  • 相关阅读:
    实体类调用泛型父类中的静态方法中执行CRUD——第一版
    Windows10 磁盘100%解决办法
    Torchvision 源码安装[Ubuntu]
    Pycharm调试:进入调用函数后返回
    Windows 10 家庭版/专业版 彻底关闭windows update自动更新
    Windows10 家庭版 关闭Windows defender
    Windows 10 更改系统文字大小
    Ubuntu 使用命令行连接无线网
    支持向量机(SVM)
    Ubuntu系统实现将Jupyter notebook项目发布到GitHub
  • 原文地址:https://www.cnblogs.com/mthoutai/p/6897666.html
Copyright © 2011-2022 走看看