zoukankan      html  css  js  c++  java
  • (C/C++) 算法,编程题

    注: 如下的题目皆来自互联网,答案是结合了自己的习惯稍作了修改。

    1. 求一个数的二进制中的1的个数。

    int func(int x)
    {
        int count = 0; 
    
        while (x)
        {
            count++; 
            x = x& (x - 1); 
        }
    
        return count; 
    }

    2. 已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数,请编写函数 strcpy。

    int _tmain(int argc, _TCHAR* argv[])
    {
        const char *srcStr = "This is a source string.";
        
        //char *desStr = (char *)malloc(sizeof(srcStr));    // Or below:
        char *desStr = (char *)malloc(sizeof(char)* strlen(srcStr) + 1); 
    
        myStrcpy(desStr, srcStr);
    
        printf("Copy result: %s", desStr); 
    }
    
    char *myStrcpy(char *strDest, const char *strSrc)
    {
        if (strSrc == NULL || strDest == NULL)
        {
            return NULL; 
        }
    
        if (strDest == strSrc)
        {
            return strDest; 
        }
    
        char *strDestStart = strDest; 
    
        while (*strDest !='')
        {
            *strDest++ = *strSrc++;
        }
    
        return strDestStart;
    }

    3. 链表题:

    一个链表的结点结构

    struct Node
    {
      int data ;
      Node *next ;
    };
    typedef struct Node Node ;
    

      

    (1)已知链表的头结点head,写一个函数把这个链表逆序

    思路: 用三个指针p0,p1,p2,从头到尾依次遍历并反转结点

    int _tmain(int argc, _TCHAR* argv[])
    {
    	int linkedListLength = 5; 
    	Node *myList = new Node(); 
    	Node *p = myList; 
    	printf("Original linked list is:"); 
    	for (int i = 0; i < linkedListLength; i++)
    	{
    		Node *node = new Node(); 
    		node->data = i;
    		printf(" %d", i);
    		p->next = node;
    		p = node;
    	}
    
    	Node *reversedMyList = ReverseLinkedList(myList); 
    
    	printf("
    Reversed linked list is:"); 
    	Node *r = reversedMyList; 
    	while (r->next != NULL)
    	{
    		printf(" %d", r->data); 
    		r = r->next;
    	}
    }
    
    Node *ReverseLinkedList(Node *head)
    {
    	// NULL
    	if (head == NULL)
    	{
    		return NULL; 
    	}
    
    	// One node only.
    	if (head->next == NULL)
    	{
    		return head; 
    	}
    
    	// Two or more than two nodes.
    	Node *p0 = head; 
    	Node *p1 = p0->next; 
    	Node *p2 = p1->next;   //p2 maybe null; 
    
    	p0->next = NULL;
    
    	while (p2 != NULL)
    	{
    		p1->next = p0; 
    		p0 = p1;
    		p1 = p2;
    		p2 = p2->next; 
    	}
    		
    	p1->next = p0; 
    	return p1; 
    }
    

    (2)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序。(保留所有结点,即便大小相同)

    思路: 从head1 和 head2 中找一个较小值定义为head,然后一次用p0,p1遍历两个链表,逐步的插入到新链表里(currnt)。

    int _tmain(int argc, _TCHAR* argv[])
    {
    	Node *p0 = new Node(); 
    	Node *p1 = new Node(); 
    	int data0[5] = { 1, 3, 5, 8, 10}; 
    	int data1[3] = { 2, 6, 7 }; 
    
    	Node *head0 = p0; 
    	Node *head1 = p1; 
    	for (int i = 0; i < sizeof(data0)/sizeof(data0[0]); i++)
    	{
    		Node *tmp0 = new Node();
    		tmp0->data = data0[i]; 
    		p0->next = tmp0; 
    		p0 = p0->next; 
    	}
    
    	for (int j = 0; j < sizeof(data1)/sizeof(data1[0]); j++)
    	{
    		Node *tmp1 = new Node();
    		tmp1->data = data1[j];
    		p1->next = tmp1;
    		p1 = p1->next; 
    	}
    
    	head0 = head0->next;
    	head1 = head1->next; 
    	Node *mergedList = MergeSortedLinkedList(head0, head1); 
    }
    
    
    Node *MergeSortedLinkedList(Node *head0, Node *head1)
    {
    	if (head0 == NULL)
    	{
    		return head1; 
    	}
    
    	if (head1 == NULL)
    	{
    		return head0; 
    	}
    
    	// Set new head for new merged sorted list.
    	Node *head = NULL; 
    	Node *p0 = head0; 
    	Node *p1 = head1;
    	if (head0->data < head1->data)
    	{
    		head = head0;
    		p0 = p0->next;
    	}
    	else
    	{
    		head = head1;
    		p1 = p1->next; 
    	}
    
    	Node *current = head; 
    	while (p0 != NULL && p1 != NULL)
    	{
    		// Insert the value which is smaller.
    		if (p0->data < p1->data)
    		{
    			current->next = p0; 
    			current = p0; 
    			p0 = p0->next;
    		}
    		else
    		{
    			current->next = p1; 
    			current = p1; 
    			p1 = p1->next; 
    		}
    
    	}
    
    	// All of nodes of one list have been added into new merged list. so add the rest nodes of the other list.
    	if (p0 == NULL)
    	{
    		current->next = p1; 
    	}
    
    	if (p1 == NULL)
    	{
    		current->next = p0; 
    	}
    
    	return head; 
    }
    

    另外可以也可以采用递归(recursive)算法:

    顺便补充一下递归算法的特点,其关键就是定义一个递归公式和递归结束条件。

    (1) 递归就是在过程或函数里调用自身。
    (2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
    (3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
    (4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
     
    Node * MergeRecursive(Node *head0, Node *head1)
    {
    	if (head0 == NULL)
    	{
    		return head1;
    	}
    
    	if (head1 == NULL)
    	{
    		return head0;
    	}
    
    	Node *head = NULL;
    	if (head0->data < head1->data)
    	{
    		head = head0;
    		head->next = MergeRecursive(head0->next, head1);
    	}
    	else
    	{
    		head = head1;
    		head->next = MergeRecursive(head0, head1->next);
    	}
    
    	return head;
    }
    

      (3)Implement an Algorithm to check if the link list is in Ascending order?

    思路: 遍历链表,只要找到某个结点的值比下个结点的值大,那么就可以判断为false。

    bool IsAscendingList(Node *head)
    {
    	Node *p = head; 
    	while (p->next != NULL)
    	{
    		if (p->data > p->next->data)
    		{
    			return false; 
    		}
    
    		p = p->next; 
    	}
    	return true; 
    }
    

      

     4.  写一个函数找出一个整数数组中,第二大的数
    思路:一次遍历数组找出最大和次大数。
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int data0[5] = { 1, 3, 9, 8, 10}; 
    	//int data1[7] = { 9, 1, 2, 4, 6, 10}; 
    	int data1[7] = { 9, 4, 7, 6, 6};
    	
    	int secMax0 = FindSecondMax(data0, sizeof(data0) / sizeof(data0[0])); 
    	int secMax1 = FindSecondMax(data1, sizeof(data1) / sizeof(data1[0]));
    }
    
    int FindSecondMax(int *data, int dataLength)
    {
    	if (dataLength <= 1)
    	{
    		printf("The length of data should be more than 1."); 
    		return -1; 
    	}
    
    	int max = data[0]; 
    	int secondMax = MIN_INT;
    
    	for (int i = 1; i < dataLength; i++)
    	{
    		if (data[i] > max)
    		{
    			secondMax = max;
    			max = data[i];
    		}
    		else
    		{
    			if (data[i] > secondMax)
    			{
    				secondMax = data[i]; 
    			}
    		}
    	}
    
    	return secondMax; 
    }
    

    5. 将数a、b的值进行交换,并且不使用任何中间变量.

    思路: 采用异或运算(三次异或后,就被交换), 或加减运算。

    int _tmain(int argc, _TCHAR* argv[])
    {
    	int a = 18; 
    	int b = 32; 
    
    	// Swap withouth other variables.  3 times XOR will swap two values. (1^1 = 0, 0^0 =0, 1^0 =1, 0^1 =1). 
    	a ^= b; 
    	b ^= a; 
    	a ^= b; 
    
    	printf("a:%d, b:%d", a, b); 
    
    	// method2
    	a = a + b; 
    	b = a - b; 
    	a = a - b; 
    
    	printf("a:%d, b:%d", a, b); 
    
    }
    

    6. 题目:在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。

    分析:这道题是2006 年google 的一道笔试题。

    思路:采用bitmap或者byteArray的思路,遍历字符串,每个字符对应的整数值为index。 Array里保存字符出现的次数。

    // Assuming the char is ASCII
    char FirstSingleChar(char *str)
    {
    	int bitmap[255]; 
    	memset(bitmap, 0, 255 * sizeof(int)); 
    
    	char *p = str;
    
    	while (*p != '')
    	{
    		bitmap[*p]++; 
    		p++; 
    	}
    
    	p = str;	
    	while (*p!='')
    	{
    		if (bitmap[*p] == 1)
    		{
    			return *p; 
    		}
    	}
    
    	return ''; 
    }
    

    7.题目:输入一个表示整数的字符串,把该字符串转换成整数并输出。
    例如输入字符串"345",则输出整数345。

    思路: 遍历字符串,逐字符转换为整数(和‘0'做差), 其中注意一下对负数和数字的判断。

    int ConvertStrToInt(char *str)
    {
    	char *p = str; 
    	int result = 0; 
    	int asciiToInt = 0; 
    	bool isPostive = true; 
    
    	if (*p == '-')
    	{
    		isPostive = false;
    		p++; 
    	}
    	else if (*p == '+')
    	{
    		p++; 
    	}
    
    	while (*p != '')
    	{
    		if (IsNumber(*p))
    		{
    			asciiToInt = *p - '0';
    			result = result * 10 + asciiToInt;
    			p++;
    		}
    		else
    		{
    			//Had better throw exception here.
    			printf("Illegal number: %c", *p); 
    			break; 
    		}
    	}
    
    	if (!isPostive)
    	{
    		result = 0 - result; 
    	}
    
    	return result; 
    }
    

    8.  Reverse a string. 

    思路: 用两个指针指向一头一尾。然后向中间遍历,并逐个字符交换。

    int _tmain(int argc, _TCHAR* argv[])
    {
    	// char *strForTest = "+345abc" will cause "access violation writing location". http://stackoverflow.com/questions/14664510/access-violation-writing-location
    	char strForTest[] = "I like money"; 
    	ReverseWordsInSentence(strForTest); 
    }
    
    
    void ReverseString(char *str)
    {
    	int strLength = strlen(str); 
    	ReverseStringInFixedLength(str, strLength); 
    }
    
    void ReverseStringInFixedLength(char *str, int strLength)
    {
    	char *p1 = str;
    	char *p2 = str + strLength -1;
    	char tmp;
    	while (p1 < p2)
    	{
    		// Swap two chars. 
    		tmp = *p1;
    		*p1 = *p2;
    		*p2 = tmp;
    
    		p1++;
    		p2--;
    	}
    }
    

      

    9. Revese words in a sentense. for example. reverse "I like money" to "money like I". 

    思路:Reverse the whole string, then reverse each word. Using the reverseStringInFixedLength() above.

    void ReverseWordsInSentence(char *sen)
    {
    	ReverseString(sen); 
    
    	char *pStartOfWord = sen; 
    	char *p = pStartOfWord; 
    
    	while (*p != '')
    	{
    		// Skip blank spaces. 
    		while (*p == ' ' && *p != '')
    		{
    			p++; 
    		}
    
    		pStartOfWord = p; 
    
    		while (*p != ' ' && *p != '')
    		{
    			p++; 
    		}
    		
    		int wordLength = p - pStartOfWord; 
    
    		ReverseStringInFixedLength(pStartOfWord, wordLength);
    	}
    }
    

    10.  给出一个数组,还有一个给定的数,打印出数组中的一对数(不重复),使其和等于指定的数

    思路:先排序(快排),然后再用两个指针从头尾依次向中间遍历。如果和大于期待的值,那么左移right指针,如果小于期待的值,那么右移left指针。

    For sorted array,  the time complexity is O(n).   
    For unsorted array, we may do a quick sort and then call our method.  The time complexity is O(nlogn).
    
    Here is the C++ sample codes, and I have checked it works well. 
    
    int _tmain(int argc, _TCHAR* argv[])
    {
           int nums[7] = { 1, 2, 3, 3, 4, 4, 5 }; 
    
           printUniquePairs(nums, 7, 7); 
    
    }
    
    void printUniquePairs(int *numbers, int numbersLength, int expectedSum)
    {
           int sum = 0; 
    
           //Augrments judgements. e.g. Null, length. 
           if (numbersLength < 2)
           {
                  printf("Number length should be more than 2.");
                  return; 
           }
    
           // Quick sort. 
           QuickSort(numbers); 
    
           // Use two points (left, and right) moving from two sides into the center.
           int *p1 = numbers; 
           int *p2 = numbers + numbersLength - 1; 
           int previousP1Value; 
           int previousP2Value; 
    
           while (p1 < p2)
           {
                  sum = *p1 + *p2; 
                  previousP1Value = *p1;
                  previousP2Value = *p2;
    
                  if (sum == expectedSum)
                  {
                         printf("Print unique pair: %d, %d.", *p1, *p2);
    
                         p1++; 
                         p2--; 
    
                         // If the value is duplicated, then skip. 
                         if (previousP1Value == *p1)
                         {
                               p1++;
                         }
    
                         if (previousP2Value == *p2)
                         {
                               p2--;
                         }
    
                  }
                  else if (sum < expectedSum)
                  {
                         p1++; 
    
                         // If the value is duplicated, then skip. 
                         if (previousP1Value == *p1)
                         {
                               p1++; 
                         }
                  }
                  else if (sum > expectedSum)
                  {
                         p2--; 
    
                         if (previousP2Value == *p2)
                         {
                               p2--; 
                         }
                  }
           }
    

      

  • 相关阅读:
    Scala篇:Scala环境及IDEA配置
    大数据篇:Hive
    大数据篇:Flume
    大数据篇:Kafka
    15.百万考生成绩如何排序
    Tomcat 架构原理解析到架构设计借鉴
    服务设计思考:平台化
    Druid:通过 Kafka 加载流数据
    12.分而治之-归并排序
    11.经典O(n²)比较型排序算法
  • 原文地址:https://www.cnblogs.com/fdyang/p/4387663.html
Copyright © 2011-2022 走看看