秋招总结之手写代码

zhyjc6于2020-11-16发布 约4791字·约10分钟 本文总阅读量

1. 不使用任何中间变量如何将a、b的值进行交换

2. 求一个字符串最长回文子串

//马拉车算法
string longestPalindrome(string s) {
    int n = s.size();
    if (n < 2) return s;
    string ss = "#";
    for (auto c : s) {
        ss += c;
        ss += '#';
    }
    int nn = ss.size();
    vector<int> dp(nn, 0);
    int mid = 0, right = 0, maxMid = 0, maxLen = 0;
    for (int i = 1; i < nn; i++) {
        if (i < right) {
            int j = 2 * mid - i;
            if (j >= 0) {
                dp[i] = min(right-i, dp[j]);
            }
        }
        while (i-dp[i]-1 >= 0 && i+dp[i]+1 < nn && ss[i-dp[i]-1] == ss[i+dp[i]+1]) {
            dp[i]++;
        }
        if (i + dp[i] > right) {
            right = i + dp[i];
            mid = i;
        }
        if (maxLen < dp[i]) {
            maxLen = dp[i];
            maxMid = i;
        }
    }
    int start = (maxMid - maxLen) / 2;
    return s.substr(start, maxLen);
}

3. 最长公共子序列

\[dp[i][j] = \begin{cases} 0 & 若i=0或j=0\\ dp[i-1][j-1]+1 & 若i,j>0且x_i = y_j \\ max(dp[i][j-1], dp[i-1][j]) & 若i,j > 0 且 x_i \ne y_j \end{cases}\]
int longestCommonSubsequence(string text1, string text2) {
    int m = text1.size();
    int n = text2.size();
    int dp[m+1][n+1];
    bzero(dp, sizeof(dp));
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (text1[i] == text2[j]) {
                dp[i+1][j+1] = dp[i][j] + 1;
            } else {
                dp[i+1][j+1] = max(dp[i][j+1], dp[i+1][j]);
            }
        }
    }
    return dp[m][n];
}

4. 编程实现strcpy函数

/**
 * v5.6.3
 * strcpy - Copy a %NUL terminated string
 * @dest: Where to copy the string to
 * @src: Where to copy the string from
 */
char *strcpy(char *dest, const char *src) {
	char *tmp = dest;

	while ((*dest++ = *src++) != '\0')
		/* nothing */;
	return tmp;
}

5. 编程实现strncpy函数

/**
 * v5.6.3
 * strncpy - Copy a length-limited, C-string
 * @dest: Where to copy the string to
 * @src: Where to copy the string from
 * @count: The maximum number of bytes to copy
 *
 * The result is not %NUL-terminated if the source exceeds
 * @count bytes.
 *
 * In the case where the length of @src is less than  that  of
 * count, the remainder of @dest will be padded with %NUL.
 *
 */
char *strncpy(char *dest, const char *src, size_t count) {
	char *tmp = dest;

	while (count) {
		if ((*tmp = *src) != 0)
			src++;
		tmp++;
		count--;
	}
	return dest;
}

6. 编程实现strcat函数

/**
 * v5.6.3
 * strcat - Append one %NUL-terminated string to another
 * @dest: The string to be appended to
 * @src: The string to append to it
 */
char *strcat(char *dest, const char *src) {
	char *tmp = dest;

	while (*dest)
		dest++;
	while ((*dest++ = *src++) != '\0')
		;
	return tmp;
}

7. 编程实现strncmp函数

/**
 * v5.6.3
 * strncmp - Compare two length-limited strings
 * @cs: One string
 * @ct: Another string
 * @count: The maximum number of bytes to compare
 */
int strncmp(const char *cs, const char *ct, size_t count) {
	unsigned char c1, c2;

	while (count) {
		c1 = *cs++;
		c2 = *ct++;
		if (c1 != c2)
			return c1 < c2 ? -1 : 1;
		if (!c1)
			break;
		count--;
	}
	return 0;
}

8. 编程实现memcpy函数

/**
 * v5.6.3
 * memcpy - Copy one area of memory to another
 * @dest: Where to copy to
 * @src: Where to copy from
 * @count: The size of the area.
 *
 * You should not use this function to access IO space, use memcpy_toio()
 * or memcpy_fromio() instead.
 */
void *memcpy(void *dest, const void *src, size_t count) {
	char *tmp = dest;
	const char *s = src;

	while (count--)
		*tmp++ = *s++;
	return dest;
}

9. 编程实现memmove函数

/**
 *v5.6.3
 * memmove - Copy one area of memory to another
 * @dest: Where to copy to
 * @src: Where to copy from
 * @count: The size of the area.
 *
 * Unlike memcpy(), memmove() copes with overlapping areas.
 */
void *memmove(void *dest, const void *src, size_t count) {
	char *tmp;
	const char *s;

	if (dest <= src) {
		tmp = dest;
		s = src;
		while (count--)
			*tmp++ = *s++;
	} else {
		tmp = dest;
		tmp += count;
		s = src;
		s += count;
		while (count--)
			*--tmp = *--s;
	}
	return dest;
}

10. 编程实现memcmp函数

/**
 * v5.6.3
 * memcmp - Compare two areas of memory
 * @cs: One area of memory
 * @ct: Another area of memory
 * @count: The size of the area.
 */
int memcmp(const void *cs, const void *ct, size_t count) {
	const unsigned char *su1, *su2;
	int res = 0;

	for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
		if ((res = *su1 - *su2) != 0)
			break;
	return res;
}

11. 求完全二叉树的最后一个结点(快手一面)

完全二叉树只有最后一层结点可能不满,其它层的结点都是满的。如果最后一层结点也是满的,那就是满二叉树,满二叉树也是完全二叉树。

TreeNode *getLastNode(TreeNode *root) {
    if(root == NULL || root->left == NULL)    //递归出口,如果根为空,或者根为叶子节点。完全二叉树只需判定左儿子是否为空即可判定是否为叶子节点
        return root;

    int lh = getHeight(root->left);    //左子树高度
    int rh = getHeight(root->right);  //右子树高度
    if(lh > rh)
        return getLastNode(root->left);
    else
        return getLastNode(root->right);
}

int getHeight(TreeNode *root) {
    int res = 0;
    while (root) {
    	++res;
        root = root->left;
    }
    return res;
}

12. 求小数的循环节(快手一面)

两个整数相除,如果得到结果是无限循环小数,求出循环节。循环节是无限循环小数中循环出现的那一部分,比如 1 / 7 = 0.1428571428571428…,那么142857就是循环节;1 / 3 = 0.33333,3就是循环节。如果没有循环节,则返回0。

//参考:http://www.jeepxie.net/article/874643.html
string solve(int n, const int d) {
	n %= d;
	map<int, int> Pos; //记录每一次的 被除数 以及 被除数在循环小数中的位置
	string ans; //保存除下来的小数

	while (1) {
		n *= 10;
		if (Pos.find(n) != Pos.end()) { //被除数已经出现过,通过哈希表获取长度,返回循环节
			int len = ans.size() - Pos[n];
			return ans.substr(Pos[n], len);
		}

		Pos[n] = ans.size(); // 如果被除数没有出现过,则把 被除数的位置 更新为ans的长度
		if (n < d) { //被除数 小于 除数的时候 ans补上字符 0
			ans += "0"; 
			continue;
		}
		ans += (char)(n / d + '0'); //整数转换成字符
		n %= d;
		if (n == 0) { //如果不是循环小数
			break;
		}
	}
	return  "";
}