algorithm:基于C++和Python(三)

文章目录

  • 21.合并两个链表
    • C++版本
    • Python
  • 22.括号生成
    • C++ 版本
    • Python 版本
  • 23.合并k个有序链表
    • C++版本
    • Python版本
  • 24.两两交换链表中的节点
    • C++版本
    • Python版本
  • 25. k个一组翻转链表
    • C++版本
    • Python
  • 26.删除排序数组中的重复项
    • C++版本
    • Python版本
  • 27.移除元素
    • C++版本
    • Python版本
  • 28.实现strStr()函数
    • C++版本
    • Python版本
  • 29.两数相除
    • C++ 版本
    • Python版本
  • 30.与所有单词相关联的子串
    • C++版本
    • Python 版本

21.合并两个链表

将两个有序链表合并为一个新的有序链表并返回
算法思想:按部就班写吧?

C++版本

struct ListNode{
    int val;
    ListNode* next;
};

ListNode *merge2node(ListNode *head1, ListNode *head2){
    if(head1==NULL||head2==NULL) {
        return head1? head1:head2;
    }
    ListNode *start = (ListNode*)malloc(sizeof(ListNode));
    start->val = 0;
    ListNode *end = start;
    ListNode *h1 = head1->next;
    ListNode *h2 = head2->next;

    while (h1||h2) {
        if(h1==NULL||h2==NULL){
            end->next = h1 ? h1:h2;
            if(h1==NULL) h2 = h2->next;
            else h1 = h1->next;
            end = end->next;
            continue;
        }
        if (h1->val <= h2->val) {
            end->next = h1;
            h1 = h1->next;
        }
        else{
            end->next= h2;
            h2 = h2->next;
        }
        end = end->next;
    }
    end->next = NULL;
    return start;
}
void printListNode(ListNode *head){
    if(head==NULL) return;
    ListNode *tmp = head;
    while (tmp!=NULL) {
        cout<<tmp->val<<"->";
        tmp = tmp->next;
    }
    cout<<endl;
}
ListNode *createListNode(vector<int> nums){
    ListNode *head,*end,*node;
    head = (ListNode*)malloc(sizeof(ListNode));
    end = head;
    for(int i=0;i<nums.size();i++){
        node = (ListNode*)malloc(sizeof(ListNode));
        node->val = nums[i];
        end->next = node;
        end = node;
    }
    end->next = NULL;
    return head;
}
int main(){
    vector<int> nums1 = {1,2,4};
    vector<int> nums2 = {1,3,4,5};
    ListNode *head1 =createListNode(nums1);
    ListNode *head2 =createListNode(nums2);
    printListNode(head1);
    printListNode(head2);
    ListNode *head = merge2node(head1, head2);
    printListNode(head);
}
//我尝试将一个链表的值赋给另一个链表的值报错
//Debug: thread 1: EXC_BAD_ACCESS (code=1, address=0x500000004)
//int main(){
//    vector nums1 = {1,2,4};
//    ListNode *head1 =createListNode(nums1);
//    ListNode *head2=head1;
//    head2->val = head1->val;
//
//    printListNode(head2);
//
//}

Python

class ListNode(object):
    def __init__(self,val):
        self.val = val
        self.next = None

def createListNode(l):
    """
    :param l: list
    :return: ListNode
    """
    head = ListNode(0)
    end = head
    for i in l:
        end.next = ListNode(i)
        end = end.next
    end.next = None
    return head
def printListNode(head):
    """
    :param head: ListNode
    :return:
    """
    tmp =head.next
    while(tmp!=None):
        print(tmp.val,end="->")
        tmp = tmp.next
    print("")
    print("打印完成!")

def merge2ListNode(h1,h2):
    """
    :param head1: ListNode
    :param head2: ListNode
    :return: ListNode
    """
    h = ListNode(0)
    head = h
    head1 = h1.next
    head2 = h2.next
    while(head1 or head2):
        if head1==None or head2==None:
            head.next = head1 if not head2 else head2
            head = head.next
            if head1==None:
                head2 = head2.next
            else:
                head1 = head1.next
            continue
        if head1.val>=head2.val:
            head.next = head2
            head2 = head2.next
        else:
            head.next = head1
            head1 = head1.next
        head = head.next
    return h
l1 = [1,4,5,7]
l2 = [2,3,6]
head1 = createListNode(l1)
head2 = createListNode(l2)
printListNode(head1)
printListNode(head2)
head = merge2ListNode(head1,head2)
printListNode(head)

22.括号生成

给定一个数字n,返回所有可能生成的有效的n个括号组合。
算法思想:采用回溯算法,通过两个条件获取我们想要的括号组合。C++和Python算法一致。

C++ 版本

void generator(vector<vector<char>> &res,vector<char> path, int left, int n){
    if(path.size()==2*n){
        if(left==0) res.push_back(path);
        return;
    }
    if(left<n){
        path.push_back('(');
        generator(res, path, left+1,n);
        path.pop_back();
    }
    if(left>0){
        path.push_back(')');
        generator(res, path, left-1, n);
        path.pop_back();
    }
}
vector<vector<char>> generatorParenthesis(int n){
    vector<vector<char>> res;
    int left=0;
    vector<char> path;
    generator(res, path, left, n);
    return res;
}
void printres(vector<vector<char>> res){
    long n = res.size();
    long m = res[0].size();
    for(int i=0;i<n;i++){
        for (int j=0; j<m; j++) {
            cout<<res[i][j];
        }
        if(i < n-1) cout<<',';
        else cout<<endl;
    }
}
int main(){
    int n = 3;
    vector<vector<char>> res;
    res = generatorParenthesis(n);
    printres(res);
}

Python 版本

def genParenthesis(n):

    def dfs(left,path,res,n):
        if len(path) == 2*n:
            if left == 0:
                res.append("".join(path))
            return
        if left < n:
            path.append("(")
            dfs(left+1,path,res,n)
            path.pop()
        if left > 0:
            path.append(')')
            dfs(left-1,path,res,n)
            path.pop()
        return res
    res = []
    path = []
    left = 0
    r = dfs(left,path,res,n)
    return r
print(genParenthesis(3))

23.合并k个有序链表

给定k个有序链表,返回合并后的排序链表,请分析和描述算法复杂度。
算法思想:python暂时采用调用合并两个链表;C++我尝试将链表中的所有值取出来,排序后构建一个新链表。

C++版本

struct ListNode{
    int val;
    ListNode* next;
};
ListNode *mergeKListNode(vector<ListNode *> ll){
    vector<int> nums;
    ListNode *lnext;
    for(int i=0;i<ll.size();i++){
        lnext = ll[i];
        while (lnext->next) {
            nums.push_back(lnext->next->val);
            lnext = lnext->next;
        }
    }
    cout<<nums.size()<<endl;
    sort(nums.begin(), nums.end());
    ListNode *head,*end,*tmp;
    head = (ListNode*)malloc(sizeof(ListNode));
    end = head;
    head->val = 0;
    for(int i=0;i<nums.size();i++){
        tmp = (ListNode*)malloc(sizeof(ListNode));
        tmp->val = nums[i];
        end->next = tmp;
        end = end->next;
    }
    end->next = NULL;
    return head;
}

void printListNode(ListNode *head){
    if(head==NULL) return;
    ListNode *tmp = head;
    while (tmp!=NULL) {
        cout<<tmp->val<<"->";
        tmp = tmp->next;
    }
    cout<<endl;
}
ListNode *createListNode(vector<int> nums){
    ListNode *head,*end,*node;
    head = (ListNode*)malloc(sizeof(ListNode));
    end = head;
    for(int i=0;i<nums.size();i++){
        node = (ListNode*)malloc(sizeof(ListNode));
        node->val = nums[i];
        end->next = node;
        end = node;
    }
    end->next = NULL;
    return head;
}
int main(){
    vector<int> v1 = {1,4,5};
    vector<int> v2 = {1,3,4};
    vector<int> v3 = {2,6};
    ListNode *head1 = createListNode(v1);
    ListNode *head2 = createListNode(v2);
    ListNode *head3 = createListNode(v3);
    vector<ListNode *> ll;
    ll.push_back(head1);
    ll.push_back(head2);
    ll.push_back(head3);
    ListNode *head = mergeKListNode(ll);
    printListNode(head);
}

Python版本

class ListNode(object):
    def __init__(self,val):
        self.val = val
        self.next = None

def createListNode(l):
    """
    :param l: list
    :return: ListNode
    """
    head = ListNode(0)
    end = head
    for i in l:
        end.next = ListNode(i)
        end = end.next
    end.next = None
    return head
def printListNode(head):
    """
    :param head: ListNode
    :return:
    """
    tmp =head.next
    while(tmp!=None):
        print(tmp.val,end="->")
        tmp = tmp.next
    print("")
    print("打印完成!")
def merge2ListNode(h1,h2):
    """
    :param head1: ListNode
    :param head2: ListNode
    :return: ListNode
    """
    h = ListNode(0)
    head = h
    head1 = h1.next
    head2 = h2.next
    while(head1 or head2):
        if head1==None or head2==None:
            head.next = head1 if not head2 else head2
            head = head.next
            if head1==None:
                head2 = head2.next
            else:
                head1 = head1.next
            continue
        if head1.val>=head2.val:
            head.next = head2
            head2 = head2.next
        else:
            head.next = head1
            head1 = head1.next
        head = head.next
    return h
def mergeKListNode(ll):
    """
    :param l: [ListNode]
    :return: ListNode
    """
    return reduce(merge2ListNode,ll)

l1 = [1,4,5]
l2 = [1,3,4]
l3 = [2,6]
ll = []
ll.append(createListNode(l1))
ll.append(createListNode(l2))
ll.append(createListNode(l3))
res = mergeKListNode(ll)
printListNode(res)

24.两两交换链表中的节点

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表
算法思想:直接遍历通过双指针做转换,也可以尝试递归的方法。

C++版本

struct ListNode{
    int val;
    ListNode* next;
};
ListNode *changeALLNode(ListNode *l){
    ListNode *ll = l->next;
    if(l->next && l->next->next){
        l->next = l->next->next;
    }
    ListNode *tmp1,*tmp2;
    while (ll && ll->next) {
        tmp1 = ll->next; //tmp1 = 2
        ll->next = tmp1->next;
        tmp1->next = ll;
        tmp2 = ll;
        ll = ll->next;
        if (ll && ll->next){
        tmp2->next = ll->next;
        }
        else if(ll){
            tmp2->next = ll;
        }
        else {}

    }
    return l;
}
void printListNode(ListNode *head){
    if(head==NULL) return;
    ListNode *tmp = head;
    while (tmp!=NULL) {
        cout<<tmp->val<<"->";
        tmp = tmp->next;
    }
    cout<<endl;
}
ListNode *createListNode(vector<int> nums){
    ListNode *head,*end,*node;
    head = (ListNode*)malloc(sizeof(ListNode));
    end = head;
    for(int i=0;i<nums.size();i++){
        node = (ListNode*)malloc(sizeof(ListNode));
        node->val = nums[i];
        end->next = node;
        end = node;
    }
    end->next = NULL;
    return head;
}
int main(){
    vector<int> nums = {1,2,3,4,5,6,7,8};
    ListNode *l = createListNode(nums);
    printListNode(l);
    ListNode *head = changeALLNode(l);
    printListNode(head);
    
}

Python版本

class ListNode(object):
    def __init__(self,val):
        self.val = val
        self.next = None

def createListNode(l):
    """
    :param l: list
    :return: ListNode
    """
    head = ListNode(0)
    end = head
    for i in l:
        end.next = ListNode(i)
        end = end.next
    end.next = None
    return head
def printListNode(head):
    """
    :param head: ListNode
    :return:
    """
    tmp =head.next
    while(tmp!=None):
        print(tmp.val,end="->")
        tmp = tmp.next
    print("")
    print("打印完成!")

def changeALLNode(head):
    h = head.next
    head.next = h.next
    def change2Node(h):

        if(h and h.next):

            tmp1 = h.next
            h.next = tmp1.next
            tmp1.next = h

            tmp2 = h
            h = h.next
            if(h and h.next):
                tmp2.next = h.next
                change2Node(h)
            elif(h):
                tmp2.next = h
                return
            else:
                return
        else:
            return
    change2Node(h)

l = [1,2,3,4,5]
head1 = createListNode(l)
printListNode(head1)
changeALLNode(head1)
printListNode(head1)

25. k个一组翻转链表

给定一个链表,每k个节点一组进行翻转,并返回翻转后的链表。如果节点综述不是k的整数倍,那么将剩余节点保留原有顺序。
算法思想:可以采用递归,也可以直接写。

C++版本

struct ListNode{
    int val;
    ListNode* next;
};
ListNode *nextN(ListNode *head,int n){
    ListNode *start,*end;
    start = head;
    for(int i=0;i<n;i++){
        end = start;
        if(start->next){
             start = start->next;
        }
        else return NULL;
    }
    return end;
}

ListNode *reverseKNode(ListNode *l,int n){
    ListNode *ll = l->next;
    ListNode *nextn = nextN(ll, n);
    if(nextn){
        l->next = nextn;
    }
    else return l;
    
    ListNode *ptr[n];
    
    while (ll && nextn) {
        for (int i=0; i<n; i++) {
            ptr[i] = ll;
            ll = ll->next; // ll指向第n+1个元素
        }
        for(int i=0;i<n-1;i++){
            ptr[n-1-i]->next = ptr[n-2-i];
        }
        nextn = nextN(ll, n);
        if (ll && nextn){
            ptr[0]->next = nextn;
        }
        else if(ll){
            ptr[0]->next = ll;
        }
        else {}
    }
    return l;
}
void printListNode(ListNode *head){
    if(head==NULL) return;
    ListNode *tmp = head->next;
    while (tmp!=NULL) {
        cout<<tmp->val<<"->";
        tmp = tmp->next;
    }
    cout<<endl;
}
ListNode *createListNode(vector<int> nums){
    ListNode *head,*end,*node;
    head = (ListNode*)malloc(sizeof(ListNode));
    end = head;
    for(int i=0;i<nums.size();i++){
        node = (ListNode*)malloc(sizeof(ListNode));
        node->val = nums[i];
        end->next = node;
        end = node;
    }
    end->next = NULL;
    return head;
}
int main(){
    vector<int> nums = {1,2,3,4,5,6,7,8};
    ListNode *l = createListNode(nums);
    printListNode(l);
    ListNode *head = reverseKNode(l, 3);
    printListNode(head);
}

Python

class ListNode(object):
    def __init__(self,val):
        self.val = val
        self.next = None

def createListNode(l):
    """
    :param l: list
    :return: ListNode
    """
    head = ListNode(0)
    end = head
    for i in l:
        end.next = ListNode(i)
        end = end.next
    end.next = None
    return head
def printListNode(head):
    """
    :param head: ListNode
    :return:
    """
    tmp =head.next
    while(tmp != None):
        print(tmp.val,end="->")
        tmp = tmp.next
    print("")
    print("打印完成!")

def nextN(ll,n):
    start = ll
    nextn = start
    for i in range(n):
        nextn = start
        if start.next:
            start = start.next
        else: return None
    return nextn

def reverseKNode(head,n):
    """
    :param head: ListNode
    :param n: int
    :return: ListNode
    """
    h = head.next
    nextn = nextN(h,n)
    if nextn:
        head.next = nextn
    else: return head

    def reverseNode(h,nextn):
        listNode = []
        for i in range(n):
            listNode.append(h)
            h = h.next
        for i in range(n-1):
            listNode[n-1-i].next = listNode[n-2-i]
        nextn = nextN(h,n)
        if nextn:
            listNode[0].next = nextn
            reverseNode(h,nextn)
        else:
            listNode[0].next = h
    reverseNode(h,nextn)
    
l = [1,2,3,4,5,6,7,8]
head1 = createListNode(l)
printListNode(head1)
reverseKNode(head1,3)
printListNode(head1)

26.删除排序数组中的重复项

给定一个排序数组,原地删除重复出现的元素,返回移除后数组的新长度。不适用额外的数组空间。
算法思想:设定一个指针表示未重复元素的终点,可以通过遍历与该指针相比较,也可以遍历元素与相邻元素比较。

C++版本

int removeDuplicates(int a[],int n){
    int tmp = 0;
    for (int i=1; i<n; i++) {
        if(a[tmp] != a[i]){
            tmp++;
            a[tmp] = a[i];
        }
    }
    return tmp+1;
}
int main(){
    int a[] = {0,1,1,2,2,2,3,4};
    int n = 8;
    int tmp = removeDuplicates(a, n);
    cout<<"tmp:"<<tmp<<endl;
}

Python版本

def remvoeDuplicates(nums):
    tmp = 0
    for i in range(1,len(nums)):
        if(nums[i] != nums[tmp]):
            tmp += 1
            nums[tmp] = nums[i]
    return tmp + 1

print(remvoeDuplicates([0,1,1,1,2,2,3,4]))

27.移除元素

给定一个数组nums和一个值val,原地移除所有数值等于val的元素,返回移除后数组的长度。
算法思想:双指针的思想,一个指针指向更新后的数组,另外一个指针遍历数组,操作都是在同一个数组。

C++版本

int removeElement(vector<int> &nums,int val){
    int i=0;
    int j=0;
    while (j<nums.size()) {
        if(nums[j]==val){
            j++;
        }
        else{
            nums[i]=nums[j];
            i++;
            j++;
        }
    }
    return i;
}
void printnums(vector<int> nums,int n){
    for(int i=0;i<n;i++){
        cout<<nums[i]<<"->";
    }
}
int main(){
    vector<int> nums = {0,0,1,1,2,3,3,4};
    int val = 3;
    int n = removeElement(nums, val);
    printnums(nums,n);
    cout<<endl;
}

Python版本

def removeElement(nums,val):
    tmp = 0
    for i in range(len(nums)):
        if nums[i]==val:
            continue
        else:
            nums[tmp] = nums[i]
            tmp += 1
    return tmp
nums = [1,2,3,3,4]
n = removeElement(nums,3)
print(nums[:n])

28.实现strStr()函数

给定一个haystack字符串和needle字符串,在haystack字符串找出needle字符串出现的第一个位置。如果不存在,则返回-1。
算法思想:暴力解法,此外,算法还有优化的空间KMP算法。

C++版本

int strStr(char *hay,char *need){
    if(!need||!hay) return NULL;
    char *ph,*pn;
    ph = hay;
    int j = 0;
    while (*ph) {
        char *tmp = ph;
        for(pn=need;*pn;pn++){
            if(*tmp != *pn) {
                break;
            }
            tmp++;
        }
        if(!*pn){
            return j;
        }
        ph++;
        j++;
    }
    return -1;
}
int main(){
    const char* hay = "hello";
    const char* need = "lo";
    int i = strStr((char*)hay,(char*)need);
    cout<<i<<endl;
}

Python版本

def strStr(s1,s2):
    for i in range(len(s1)):
        tmp = i
        for j in range(len(s2)):
            if s1[tmp]==s2[j]:
                tmp += 1
                continue
            else:
                break
        if len(s2)==tmp-i:
            return i
    return -1
print(strStr("hello","ll"))

29.两数相除

给定一个被除数和除数,将两数相除,要求不使用乘法、除法和mod运算符
算法思想:通过位运算来转化,有点像进制的转换。

C++ 版本

int div1(int dividend,int divisor){
    int sign = (float)dividend/divisor>0 ? 1:-1;
    unsigned int dvd = dividend > 0? dividend: -dividend;
    unsigned int dvs = divisor >0? divisor: -divisor;
    unsigned int bit_num[32];
    unsigned int i = 0;
    long long d = dvs;
    bit_num[i] = d;
    
    while (dvd >= d) {
        bit_num[++i] = d = d<<1;
    }
    
    int sum = 0;
    while (dvd >= dvs) {
        if(dvd >= bit_num[i]){
            sum =sum + (1<<i);
            dvd = dvd - bit_num[i];
            
        }
        i--;
    }
    return sum*sign;
}
int main(){
    cout<<div1(100, 3)<<endl;
    cout<<div1(9, 3)<<endl;
    cout<<div1(38, 3)<<endl;
}

Python版本

def div(dividend,divisor):
    if divisor==0:
        return 0x7fffffff
    sign = 1
    if dividend*divisor<0:
        sign = -1
    ans = 0
    dividend = abs(dividend)
    divisor = abs(divisor)
    subsum = 0
    while(dividend>divisor):
        cnt = 1
        if dividend < 2*divisor:
            ans += 1
            return ans
        tmp = dividend
        while(tmp>divisor):
            tmp >>= 1
            cnt <<= 1
        cnt >>= 1
        subsum = cnt*divisor
        ans += cnt
        dividend -= subsum
    return max(min(sign*ans,0x7fffffff),-2147483648)

print(div(91,3))

30.与所有单词相关联的子串

给定一个字符串和一些长度相同的单词words,在s中找到可以恰好传来words中所有单词的子串的起始位置。
算法思想:Python版本(我审题有问题,安装长度不同的单词来考虑,而且没有考虑单词重复的情况)分为两部分,首先生成一个包含单词首字母索引的字典,其次根据生成的字典做匹配,主要满足:当前单词首字母的索引 + 单词长度 = 下一个不重复的单词的索引

C++版本的思想就是从结果入手,正确的结果必然是单词长度组合,所以可以通过不同的初始尺寸去卡(遍历单词长度),在卡的过程中,当不满足条件则递增初始值(单词长度)。总体来说,C++版本的思想很好很好,值得学习。

C++版本

vector<int> findSubstring(string S,vector<string> &L){
    vector<int> result;
    if(S.size()<=0 || L.size()<=0){
        return result;
    }
    int n = S.size(), m = L.size(), l = L[0].size();
    //单词可能为多个,所以通过一个字典存储下
    map<string,int> expected;
    for(int i=0;i<m;i++){
        if(expected.find(L[i])!=expected.end()){
            expected[L[i]]++;
        }else{
            expected[L[i]] = 1;
        }
    }
    // 固定长度的单词,注意审题
    for(int i=0;i<l;i++){
        map<string,int> actual;
        int count = 0;
        int winLeft = i;
        for(int j=i;j<n-l;j+=l){
            string word = S.substr(j,l);
            if(expected.find(word)==expected.end()){
                actual.clear();
                count = 0;
                winLeft = j+l;
                continue;
            }
            count++;
            if(actual.find(word)==actual.end()){
                actual[word] = 1;
            }else{
                actual[word]++;
            }
            if(actual[word]>expected[word]){
                string tmp;
                do{
                    tmp = S.substr(winLeft,l);
                    count--;
                    actual[tmp]--;
                    winLeft += l;
                }while (tmp!=word);
            }
            if(count==m){
                result.push_back(winLeft);
                string tmp = S.substr(winLeft,l);
                actual[tmp]--;
                winLeft += l;
                count--;
            }
        }
    }
    return result;
}
int main(int argc,char**argv){
    string s = "barfoothefoobarman";
    vector<string> l;
    l.push_back("foo");
    l.push_back("bar");
    vector<int> indics = findSubstring(s, l);
    for (int i=0; i<indics.size(); i++) {
        cout<<indics[i]<<" ";
    }
    cout<<endl;
}

Python 版本

def findSubString(s,words):
    n = len(words)
    d = {} # 单词-索引列表  键值对
    l = [] # 提取的单词索引列表
    wordl = [] # 单词防重
    res = []
    for word in words:
        for i in range(len(s)):
            tmp = i
            for j in range(len(word)):
                if s[tmp] == word[j]:
                    if j == len(word)-1:
                        if word in d.keys():
                            d[word].append(i)
                        else:
                            d[word] = []
                            d[word].append(i)
                    tmp += 1
                    continue
                else:
                    break
    newd = {}
    tmpkey = 0
    for key,value in d.items():
        l = l + value
        for val in value:
            newd[val] = key
    l = sorted(l)
    for i in range(len(l)):
        tmp = i
        while(tmp<len(l)):

            if tmp == i:
                wordl.append(newd[l[tmp]])
                tmpkey = l[tmp] + len(newd[l[tmp]])
            elif newd[l[tmp]] not in wordl and tmpkey == l[tmp]:
                wordl.append(newd[l[tmp]])
                tmpkey = l[tmp] + len(newd[l[tmp]])
            else:
                break
            if len(wordl)==n:
                res.append(l[i])
                break
            tmp += 1
        i += 1
    return res
print(findSubString("viewfilexxfileedit",["edit","file"]))

enjoy!

本文代码可能有bug,还请各位看官指正,或者小伙伴们有更好的算法,欢迎评论~

你可能感兴趣的:(算法,算法,pyhton,c++)