あなたほばかですか.
13、打印1到最大的n位数
打印1到最大的n位数,如n=3时打印1到999
思路:求出最大的n位数,然后依次打印,但当n十分大事会出问题。这里涉及到大数问题。
n = 2
num = 1
for i in range(n):
num = num*10
for i in range(1,num):
print i
一个更完善的思路:
用字符串表示数字,进行进位,全排列递归输出,略复杂。
用字符串解决大数问题的思路大致如下:
字符串中的每个字符都是‘0’到‘9’之间的某个字符,用来表示数字中的一位。数字最大是n位,故需要一个n+1的字符串,最后一个为结束符号‘\0’。当实际数字不够n位的时候,在字符串的前半部分补0。如果在数字前面补0的话,就会发现n位所有十进制数其实就是n个从‘0’到‘9’的全排列。也就是说,把数字的每一位都从‘0’到‘9’排列一遍,就可以得到所有的十进制数。但是在打印的时候,数字排在前面的0不打印。
字符串中的每个字符都是‘0’到‘9’之间的某个字符,用来表示数字中的一位。数字最大是n位,故需要一个n+1的字符串,最后一个为结束符号‘\0’。当实际数字不够n位的时候,在字符串的前半部分补0。如果在数字前面补0的话,就会发现n位所有十进制数其实就是n个从‘0’到‘9’的全排列。也就是说,把数字的每一位都从‘0’到‘9’排列一遍,就可以得到所有的十进制数。但是在打印的时候,数字排在前面的0不打印。
可以参考大佬的代码:Python实现代码
14、在O(1)时间删除链表结点
思路:这个首先想到的是顺序查找,复杂度为O(n),但是不满足要求啊。
好的解决方案是这么个思路:
如果要删除结点i,先把i的下一个节点j的内容复制到i,然后把i的指针指向节点j的下一个节点。此时再删除节点j。如果删除的节点位于链表的尾部,则从链表的头节点开始,顺序遍历得到该节点的前序节点,并完成删除操作。如果链表中只有一个节点,此时删除节点后,还需要把链表的头节点设置为NULL。
还有一点需要注意,上述思路基于要删除的点存在在链表中,而我们需要O(n)的时间才能判断链表中是否有该节点。面试时要告诉面试官这个假设。
综上,进阶思路:
1、判断要删除的节点后是否有节点,若有节点,则将该节点内容复制到要删除的节点,并删除该节点
2、若链表中只有一个节点,则删除该节点
3、若要删除的节点后面没有节点(即该节点为最后一个),则遍历到该节点前一位并删除该节点
class ListNode:
def __init__(self, x = None):
self.val - x
self.next = None
def __del__(self):
self.val = None
self.next = None
class Solution:
def DeleteNode(self, pListHead, pToBeDeleted):
if not pListHead or not pToBeDeleted:
return None
if pToBeDeleted.next != None: #如果要删除的节点后面不为空,则将下一个节点复制
pToBeDeleted.val = pToBeDeleted.next.val
pToBeDeleted.next = pToBeDeleted.next.next
pToBeDeleted.next.__del__()
elif pListHead == pToBeDeleted:
pToBeDeleted.__del__()
pListHead.__del__()
else:
pNode = pListHead
while pNode != pToBeDeleted:
pNode = pNode.next
pNode.next = None
pToBeDeleted.__del__()
代码来自于
https://blog.csdn.net/slibra_l/article/details/78151979
15、调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
思路:首先送上我的low代码,没看懂书上牛逼的算法。。。
def reOrderArray(array):
# write code here
ji = []
ou = []
alle = []
x=[]
for i in array:
if i % 2 == 0:
ou.append(i)
ou.sort()
else:
ji.append(i)
ji.sort()
alle.append(ji)
alle.append(ou)
for i in alle:
for j in i:
x.append(j)
return x
class Solution {
public:
void reOrderArray(vector<int> &array) {
vector<int> result;
int num=array.size();
for(int i=0;i<num;i++)
{
if(array[i]%2==1)
result.push_back(array[i]);
}
for(int i=0;i<num;i++)
{
if(array[i]%2==0)
result.push_back(array[i]);
}
array=result;
}
};
16、链表中倒数第K个结点
输入一个单向链表,输出该链表中倒数第k个结点。
思路:
两个指针,先让第一个指针和第二个指针都指向头结点,然后再让第一个指正走(k-1)步,到达第k个节点。然后两个指针同时往后移动,当第一个结点到达末尾的时候,第二个结点所在位置就是倒数第k个节点了。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindKthToTail(self, head, k):
# write code here
l=[]
while head!=None:
l.append(head)
head=head.next
if k>len(l) or k<1:
return
return l[-k]
时间复杂度O(n),一次遍历即可
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
ListNode pre=null,p=null;
//两个指针都指向头结点
p=head;
pre=head;
//记录k值
int a=k;
//记录节点的个数
int count=0;
//p指针先跑,并且记录节点数,当p指针跑了k-1个节点后,pre指针开始跑,
//当p指针跑到最后时,pre所指指针就是倒数第k个节点
while(p!=null){
p=p.next;
count++;
if(k<1){
pre=pre.next;
}
k--;
}
//如果节点个数小于所求的倒数第k个节点,则返回空
if(count<a) return null;
return pre;
}
}
17、反转链表
递归的方法其实是非常巧的,它利用递归走到链表的末端,然后再更新每一个node的next 值 ,实现链表的反转。而newhead 的值没有发生改变,为该链表的最后一个结点,所以,反转后,我们可以得到新链表的head。
注意关于链表问题的常见注意点的思考:
1、如果输入的头结点是 NULL,或者整个链表只有一个结点的时候
2、链表断裂的考虑
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
if pHead==None or pHead.next==None:
return pHead
last = None
while pHead:
tmp = pHead.next
pHead.next=last
last = pHead
pHead=tmp
return last
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
//如果链表为空或者链表中只有一个元素
if(pHead==NULL||pHead->next==NULL) return pHead;
//先反转后面的链表,走到链表的末端结点
ListNode* pReverseNode=ReverseList(pHead->next);
//再将当前节点设置为后面节点的后续节点
pHead->next->next=pHead;
pHead->next=NULL;
return pReverseNode;
}
};
18、合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。思路:
初始化两个链表头,其中一个表头用以记录两个单调递增链表比较后的结果,另一个用以返回结果。
用while循环:
①如果两个链表不为空,比较进行,并将小的那个赋给合并的链表头。小表头继续走一步,合并表头继续走一步。
②如果两个链表有其一为空,那么跳出循环,并将另一不为null的链表的后续部分赋给合并链表。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
mergeHead = ListNode(0)
p = mergeHead
while pHead1 and pHead2:
if pHead1.val >= pHead2.val:
mergeHead.next = pHead2
pHead2 = pHead2.next
else:
mergeHead.next = pHead1
pHead1 = pHead1.next
mergeHead = mergeHead.next
if pHead1:
mergeHead.next = pHead1
elif pHead2:
mergeHead.next = pHead2
return p.next
递归版本
public ListNode Merge(ListNode list1,ListNode list2) {
if(list1 == null){
return list2;
}
if(list2 == null){
return list1;
}
if(list1.val <= list2.val){
list1.next = Merge(list1.next, list2);
return list1;
}else{
list2.next = Merge(list1, list2.next);
return list2;
}
}