算法学习:(单)链表问题

一 链表倒置

链表倒置是链表的基本操作之一。

题目 一 Reverse Linked List

LeetCode 206 Reverse Linked List

Reverse a singly linked list.
Example:
Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL
Follow up:
A linked list can be reversed either iteratively or recursively. Could you implement both?

题目提示可以用 迭代 或 递归 两种方法来解。

  • 迭代方法
    如图: 两个指针 head p 分别指向 表头,欲倒置的元素. 为了使下一个欲倒置的元素不会 野 掉, 还需要一个指针 tmp 来保护它

    1. p->next 指向 head
    2. head->next 指向 tmp
    3. head = p, p = tmp, tmp 保护下一个欲倒置的元素

    代码:

    class Solution {
    public:
        ListNode* reverseList(ListNode* head) {
            if(!head) return NULL;
            if(!head->next) return head;
    
            ListNode *p,*tmp;
            p = head->next;
            tmp = p->next;
            head->next = NULL;
    
            while(p1){
                p->next = head;
                head = p;
                p = tmp;
                if(tmp)
                    tmp = tmp->next;
            }
    
            return head;
        }
    };
  • 递归方法
    思想和上面一样,只不过代码的写法不同:

    class Solution {
    public:
        ListNode* reverseList(ListNode* head) {
            if(!head || !head->next){
                return head;
            }
    
            ListNode* p = reverseList(head->next);
            head->next->next = head;
            head->next = NULL;
            return p;
        }
    };

    递归的方法代码简洁高效,在很多链表题目中都会用到它,所以特别重要。例如下一题

阅读更多

算法学习:动态规划问题的一般解法

例题 一 : Triangle

LeetCode 120. Triangle

Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle

[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]

The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).

分析:

设三角形共有 $N$ 行, $r$ 为三角形的行, $c$ 为三角形的列。从点 $P(r,c)$ 出发,每向下走一步有两个点$P_1(r+1,c), P_2(r+1, c+1)$ 可以选择 ,如果每次都选值小的点$min(P1, P2)$,则最后得到的点的值之和即是最优解。令 $M(r,c)$ 为从 $P(r,c)$ 开始到下面的列的各条路径中,最佳路径的数字之和。

解法一:

这是一个典型的递归问题。

由此写出代码:

class Solution {
public:
    int getMinPathSum(vector<vector<int>>& triangle, int r, int c){
        if(r == triangle.size() - 1) return triangle[r][c];

        int x = getMinPathSum(triangle, r+1, c);
        int y = getMinPathSum(triangle, r+1, c+1);

        x = x<y ? x: y;

        return triangle[r][c] + x;
    }

    int minimumTotal(vector<vector<int>>& triangle) {
        return getMinPathSum(triangle, 0,0);
    }
};

代码没有问题,在 "Run Code" 时可以得出正确的结果。但是 "Submit" 却会给出 "Time Limit Exceeded",超时!

如果我们推算这个解法的时间复杂度的话,可以得到 $O(2^n)$ .这不超时就有鬼了。我们需要改进这个算法。

阅读更多

在 Qt 中使用 TreeView

提示:本文中的 Demo 已 push 到 github,可忽略本文直接到 我的github 中查看代码。

Qt 提供了 QuickControl TreeView 。但是比较奇葩的是该控件不能直接使用,而需要用户自己扩展实现。
官方给出了一个示例如下:

TreeView {
    TableViewColumn {
        title: "Name"
        role: "fileName"
        width: 300
    }
    TableViewColumn {
        title: "Permissions"
        role: "filePermissions"
        width: 100
    }
    model: fileSystemModel
}

它声明了一个 TreeView控件,该控件有 2 列,分别为 Name 和 Permissions,还有一个名为 fileSystemModel 的 model 。对用户来说,这里的 model 是一个关键性的对象,它需要用户使用 C++ 实现 ,并注册到 qml 中供 TreeView 使用。按官方的说法, model 是一个 为 tree view 提供数据的属性,它包含了 tree view 将要展示的数据。
用户的 model 必须继承于 QAbstractItemModel 类。
该类是一个抽象类,在运行中,treeview 从该类中获取用户数据,再在UI上展示。该类有如下纯虚函数,必须在子类中实现:

virtual int    columnCount(const QModelIndex &parent = QModelIndex()) const = 0;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const = 0;
virtual QModelIndex    index(int row, int column, const QModelIndex &parent = QModelIndex()) const = 0;
virtual QModelIndex    parent(const QModelIndex &index) const = 0;
virtual int    rowCount(const QModelIndex &parent = QModelIndex()) const = 0;

阅读更多

CMake 为项目添加自定义事件

为满足需求:

项目编译前需要预处理一些自定义命令,如生成代码文件,拷贝成果文件等。

解决该问题有两种方案:

add_custom_command prebuild

vcxproj 可以自定义生成事件,如:

<ItemDefinitionGroup>  
  <PreBuildEvent>  
    <Command>copy $(ProjectDir)main.cpp $(ProjectDir)copyOfMain.cpp</Command>  
    <Message>Making a copy of main.cpp </Message>  
  </PreBuildEvent>  
  <PreLinkEvent>  
<Command>copy $(ProjectDir)$(Configuration)\main.obj $(ProjectDir)$(Configuration)\copyOfMain.obj</Command>  
    <Message>Making a copy of main.obj</Message>  
  </PreLinkEvent>  
  <PostBuildEvent>  
<Command>copy $(ProjectDir)$(Configuration)\$(TargetFileName) $(ProjectDir)$(Configuration)\copyOfMyproject.exe</Command>  
    <Message>Making a copy of myproject.exe</Message>  
  </PostBuildEvent>  
</ItemDefinitionGroup>

阅读更多

Django 集成 CKEditor 踩过的坑

上一次说到了在 django 中集成 tinymce。但在使用过程中发现功能不够强大。如自定义css, 上传文件等功能缺失,所以转向功能更全的 ckeditor

该项目在github上开源。

基本按照 github 上的简介就可以将其集成到项目里。但也有一些坑:

语言设置为中文

以下设置一个都不能少:

LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True

LANGUAGES = [
    ('en', 'English'),
    ('zh-cn', 'Chinese'),
]

MIDDLEWARE_CLASSES = [
    …
    'django.middleware.locale.LocaleMiddleware',
]

上传图片

settings.py 中以下设置

MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL = '/media/'
CKEDITOR_UPLOAD_PATH = "uploads/"

INSTALLED_APPS = [
    …
    "ckeditor_uploader",
]

其中 CKEDITOR_UPLOAD_PATH 必须是相对路径,相对基地址为 MEDIA_URL

在 model 中使用时,使用 from ckeditor.fields import RichTextField , 在 form 中使用时,使用 from ckeditor_uploader.fields import RichTextUploadingFormField

阅读更多

Django 集成 tinymce

环境

  • django-1.11.8
  • python2.7+

步骤

Install

pip install django-tinymce4-lite

setting

  • 在项目的 setting.py 文件中,找到 INSTALLED_APPS 节点, 添加 tinymce
  • 在项目的 urls.py 中添加以下内容:
    from django.conf.urls import url, include
    
    urlpatterns = [
        …
        url(r'^tinymce/', include('tinymce.urls')),
        …
    ]

     

  • 在项目的 setting.py 文件中,添加节点 TINYMCE_JS_URL, 指向 tinymce.min.js 文件。由于本机服务器资源有限,故使用了CDN:
    TINYMCE_JS_URL = 'https://cdn.bootcss.com/tinymce/4.7.9/tinymce.min.js'

阅读更多